"use client";

import { useState } from "react";
import Link from "next/link";
import { useQuery } from "@tanstack/react-query";
import { fetchContentList, fetchCollections } from "@/lib/api";
import type { FieldDefinition } from "@/lib/api";

type Props = {
  name: string;
  def: FieldDefinition;
  value: string[] | string;
  onChange: (value: string[]) => void;
  required?: boolean;
  error?: unknown;
  locale?: string;
  label: React.ReactNode;
};

/** Referenced collection(s) from schema: single collection or list for polymorphic. */
function getCollections(def: FieldDefinition): string[] {
  const items = def.items as FieldDefinition | undefined;
  if (!items) return [];
  if (items.collection) return [items.collection];
  if (Array.isArray(items.collections) && items.collections.length > 0)
    return items.collections;
  return [];
}

export function ReferenceArrayField({
  name,
  def,
  value,
  onChange,
  required,
  error,
  locale,
  label,
}: Props) {
  const schemaCollections = getCollections(def);
  const singleCollection =
    schemaCollections.length === 1 ? schemaCollections[0] : null;
  const multipleCollections =
    schemaCollections.length > 1 ? schemaCollections : [];
  const valueList: string[] = Array.isArray(value)
    ? value
    : typeof value === "string"
      ? value
          .split(/[\n,]+/)
          .map((s) => s.trim())
          .filter(Boolean)
      : [];

  const [pickedCollection, setPickedCollection] = useState<string>(
    singleCollection ?? multipleCollections[0] ?? "",
  );

  const { data: collectionsData } = useQuery({
    queryKey: ["collections"],
    queryFn: fetchCollections,
    enabled: schemaCollections.length === 0,
  });

  const availableCollections =
    schemaCollections.length > 0
      ? schemaCollections
      : (collectionsData?.collections ?? [])
          .map((c) => c.name)
          .filter(
            (n) =>
              n !== "content_layout" && n !== "component_layout" && n !== "seo",
          );

  const effectiveCollection = singleCollection ?? pickedCollection;

  const listParams = { _per_page: 200, ...(locale ? { _locale: locale } : {}) };

  const singleQuery = useQuery({
    queryKey: ["content", effectiveCollection, listParams],
    queryFn: () => fetchContentList(effectiveCollection!, listParams),
    enabled: !!effectiveCollection && schemaCollections.length <= 1,
  });

  const multiQueries = useQuery({
    queryKey: ["content-multi", multipleCollections, listParams],
    queryFn: async () => {
      const results = await Promise.all(
        multipleCollections.map((coll) => fetchContentList(coll, listParams)),
      );
      return multipleCollections.map((coll, i) => ({
        collection: coll,
        items: results[i]?.items ?? [],
      }));
    },
    enabled: multipleCollections.length > 1,
  });

  type OptionItem = { slug: string; collection: string };
  const options: OptionItem[] =
    multipleCollections.length > 1 && multiQueries.data
      ? multiQueries.data.flatMap(({ collection: coll, items }) =>
          (items as { _slug?: string }[])
            .map((o) => ({
              slug: String(o._slug ?? ""),
              collection: coll,
            }))
            .filter((o) => o.slug),
        )
      : ((singleQuery.data?.items ?? []) as { _slug?: string }[])
          .map((o) => ({
            slug: String(o._slug ?? ""),
            collection: effectiveCollection ?? "",
          }))
          .filter((o) => o.slug);

  const isLoading =
    schemaCollections.length <= 1
      ? singleQuery.isLoading
      : multiQueries.isLoading;

  const add = (slug: string) => {
    if (!slug || valueList.includes(slug)) return;
    onChange([...valueList, slug]);
  };

  const addFromOption = (optionValue: string) => {
    const slug = optionValue.includes(":")
      ? optionValue.split(":")[1]!
      : optionValue;
    add(slug);
  };

  const remove = (index: number) => {
    onChange(valueList.filter((_, i) => i !== index));
  };

  const move = (index: number, dir: number) => {
    const next = index + dir;
    if (next < 0 || next >= valueList.length) return;
    const copy = [...valueList];
    const tmp = copy[index];
    copy[index] = copy[next];
    copy[next] = tmp;
    onChange(copy);
  };

  const collectionsForNew =
    multipleCollections.length > 1
      ? multipleCollections
      : effectiveCollection
        ? [effectiveCollection]
        : [];

  return (
    <div>
      <div className="mb-1 flex items-center justify-between">
        <span className="text-sm font-medium text-gray-700">{label}</span>
        {schemaCollections.length > 0 ? (
          <span className="text-xs text-gray-500">
            {schemaCollections.length === 1
              ? `Typ: ${schemaCollections[0]}`
              : `Typen: ${schemaCollections.join(", ")}`}
          </span>
        ) : null}
      </div>

      {/* Selected entries */}
      <ul className="mb-2 space-y-1.5">
        {valueList.map((slug, index) => (
          <li
            key={`${slug}-${index}`}
            className="flex items-center gap-2 rounded border border-gray-200 bg-gray-50 px-3 py-2 text-sm"
          >
            <span className="flex-1 font-mono text-gray-900">{slug}</span>
            <div className="flex items-center gap-1">
              <button
                type="button"
                onClick={() => move(index, -1)}
                disabled={index === 0}
                className="rounded p-1 text-gray-500 hover:bg-gray-200 hover:text-gray-700 disabled:opacity-40"
                title="Move up"
                aria-label="Move up"
              >
                <svg
                  className="h-4 w-4"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M5 15l7-7 7 7"
                  />
                </svg>
              </button>
              <button
                type="button"
                onClick={() => move(index, 1)}
                disabled={index === valueList.length - 1}
                className="rounded p-1 text-gray-500 hover:bg-gray-200 hover:text-gray-700 disabled:opacity-40"
                title="Move down"
                aria-label="Move down"
              >
                <svg
                  className="h-4 w-4"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M19 9l-7 7-7-7"
                  />
                </svg>
              </button>
              <button
                type="button"
                onClick={() => remove(index)}
                className="rounded p-1 text-red-600 hover:bg-red-50 hover:text-red-700"
                title="Remove"
                aria-label="Remove"
              >
                <svg
                  className="h-4 w-4"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M6 18L18 6M6 6l12 12"
                  />
                </svg>
              </button>
            </div>
          </li>
        ))}
      </ul>

      {/* Without schema collection: choose component type first */}
      {!singleCollection &&
      schemaCollections.length === 0 &&
      availableCollections.length > 0 ? (
        <div className="mb-2">
          <label className="mb-1 block text-xs font-medium text-gray-500">
            Component type
          </label>
          <select
            value={pickedCollection}
            onChange={(e) => setPickedCollection(e.target.value)}
            className="block w-full rounded border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900"
          >
            <option value="">— Select type —</option>
            {availableCollections.map((c) => (
              <option key={c} value={c}>
                {c}
              </option>
            ))}
          </select>
        </div>
      ) : null}

      {/* Add: select from existing + create new component */}
      {effectiveCollection || multipleCollections.length > 1 ? (
        <div className="flex flex-col gap-2 sm:flex-row sm:items-start">
          <select
            value=""
            onChange={(e) => {
              const v = e.target.value;
              if (v) addFromOption(v);
              e.target.value = "";
            }}
            className="block flex-1 rounded border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900"
            disabled={isLoading}
          >
            <option value="">— Select from existing —</option>
            {options.map((item) => {
              const key =
                multipleCollections.length > 1
                  ? `${item.collection}:${item.slug}`
                  : item.slug;
              const alreadySelected = valueList.includes(item.slug);
              const label =
                multipleCollections.length > 1
                  ? `${item.slug} (${item.collection})`
                  : item.slug;
              return (
                <option key={key} value={key} disabled={alreadySelected}>
                  {alreadySelected ? `${label} (already selected)` : label}
                </option>
              );
            })}
          </select>
          {collectionsForNew.length > 0 ? (
            <span className="flex shrink-0 flex-col gap-0.5">
              {collectionsForNew.length === 1 ? (
                <Link
                  href={
                    collectionsForNew[0]
                      ? `/content/${collectionsForNew[0]}/new${locale ? `?_locale=${locale}` : ""}`
                      : "#"
                  }
                  target="_blank"
                  rel="noopener noreferrer"
                  className="inline-flex items-center justify-center gap-1 rounded border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
                >
                  <span aria-hidden>+</span> New {collectionsForNew[0]} component
                </Link>
              ) : (
                <select
                  className="rounded border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900"
                  value=""
                  onChange={(e) => {
                    const c = e.target.value;
                    if (c)
                      window.open(
                        `/content/${c}/new${locale ? `?_locale=${locale}` : ""}`,
                        "_blank",
                      );
                    e.target.value = "";
                  }}
                >
                  <option value="">+ Create new component…</option>
                  {collectionsForNew.map((c) => (
                    <option key={c} value={c}>
                      {c}
                    </option>
                  ))}
                </select>
              )}
              <span className="text-xs text-gray-500">
                Open in new tab; then reload this page.
              </span>
            </span>
          ) : null}
        </div>
      ) : null}

      {schemaCollections.length === 0 && availableCollections.length === 0 ? (
        <p className="text-xs text-amber-600">
          No reference collection in schema. Set{" "}
          <code className="rounded bg-gray-100 px-1">items.collection</code> or{" "}
          <code className="rounded bg-gray-100 px-1">items.collections</code>{" "}
          in the type, or start the API and reload the page.
        </p>
      ) : null}

      {error ? (
        <p className="mt-1 text-sm text-red-600">
          {String((error as { message?: string })?.message ?? error)}
        </p>
      ) : null}
    </div>
  );
}
