"use client";

import { useState } from "react";
import Link from "next/link";
import { useQuery } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { fetchContentList, fetchCollections } from "@/lib/api";
import type { FieldDefinition } from "@/lib/api";
import { getOptionLabel } from "@/lib/referenceOptionLabel";
import {
  SearchableSelect,
  type SearchableSelectOption,
} from "./SearchableSelect";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Button } from "@/components/ui/button";

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 t = useTranslations("ReferenceArrayField");
  const schemaCollections = getCollections(def);
  const singleCollection =
    schemaCollections.length === 1 ? schemaCollections[0] : null;
  const multipleCollections =
    schemaCollections.length > 1 ? schemaCollections : [];

  /** Normalise to string[]: API may return resolved refs as objects with _slug. */
  function toSlugList(raw: unknown): string[] {
    if (Array.isArray(raw)) {
      return raw
        .map((v) =>
          typeof v === "object" && v !== null && "_slug" in v
            ? String((v as { _slug?: string })._slug ?? "")
            : typeof v === "string"
              ? v.trim()
              : "",
        )
        .filter(Boolean);
    }
    if (typeof raw === "string") {
      return raw
        .split(/[\n,]+/)
        .map((s) => s.trim())
        .filter(Boolean);
    }
    return [];
  }
  const valueList: string[] = toSlugList(value);

  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);
  };

  /** Options for the "add existing" SearchableSelect: full label, exclude already selected. */
  const addSelectOptions: SearchableSelectOption[] =
    multipleCollections.length > 1 && multiQueries.data
      ? multiQueries.data.flatMap(({ collection: coll, items: list }) =>
          (list as Record<string, unknown>[])
            .filter((i) => !valueList.includes(String(i._slug ?? "")))
            .map((i) => ({
              value: `${coll}:${i._slug ?? ""}`,
              label: getOptionLabel(i),
            }))
        )
      : ((singleQuery.data?.items ?? []) as Record<string, unknown>[])
          .filter((i) => !valueList.includes(String(i._slug ?? "")))
          .map((i) => ({
            value: String(i._slug ?? ""),
            label: getOptionLabel(i),
          }));

  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">
        {label}
        {schemaCollections.length > 0 ? (
          <p className="mt-0.5 text-xs text-gray-500">
            {schemaCollections.length === 1
              ? t("typeLabel", { collection: schemaCollections[0] })
              : t("typesLabel", { collections: schemaCollections.join(", ") })}
          </p>
        ) : null}
      </div>

      {/* Selected entries */}
      <ul className="mb-2 space-y-1.5">
        {valueList.map((slug, index) => {
          const collForSlug =
            options.find((o) => o.slug === slug)?.collection ??
            effectiveCollection ??
            null;
          return (
          <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">
              {collForSlug && (
                <Link
                  href={`/content/${collForSlug}/${encodeURIComponent(slug)}${locale ? `?_locale=${locale}` : ""}`}
                  className="rounded p-1 text-accent-700 hover:bg-accent-50 hover:text-accent-900"
                  title="Open entry"
                >
                  →
                </Link>
              )}
              <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={t("moveUp")}
                aria-label={t("moveUp")}
              >
                <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={t("moveDown")}
                aria-label={t("moveDown")}
              >
                <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={t("remove")}
                aria-label={t("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">
            {t("componentType")}
          </label>
          <Select value={pickedCollection} onValueChange={setPickedCollection}>
            <SelectTrigger className="w-full">
              <SelectValue placeholder={t("selectType")} />
            </SelectTrigger>
            <SelectContent>
              {availableCollections.map((c) => (
                <SelectItem key={c} value={c}>{c}</SelectItem>
              ))}
            </SelectContent>
          </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">
          <div className="min-w-0 flex-1">
            <SearchableSelect
              value=""
              onChange={(v) => v && addFromOption(v)}
              options={addSelectOptions}
              placeholder={t("selectFromExisting")}
              clearable={false}
              filterPlaceholder={t("filterPlaceholder")}
              emptyLabel={t("emptyLabel")}
              disabled={isLoading}
              ariaLabel={t("selectExistingAriaLabel")}
            />
          </div>
          {collectionsForNew.length > 0 ? (
            <span className="flex shrink-0 flex-col gap-0.5">
              {collectionsForNew.length === 1 ? (
                <Button variant="outline" size="sm" asChild>
                  <Link
                    href={
                      collectionsForNew[0]
                        ? `/content/${collectionsForNew[0]}/new${locale ? `?_locale=${locale}` : ""}`
                        : "#"
                    }
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    {t("newComponent", { collection: collectionsForNew[0] })}
                  </Link>
                </Button>
              ) : (
                <Select
                  value=""
                  onValueChange={(c) => {
                    if (c) window.open(
                      `/content/${c}/new${locale ? `?_locale=${locale}` : ""}`,
                      "_blank",
                    );
                  }}
                >
                  <SelectTrigger className="w-full">
                    <SelectValue placeholder={t("createNewComponent")} />
                  </SelectTrigger>
                  <SelectContent>
                    {collectionsForNew.map((c) => (
                      <SelectItem key={c} value={c}>{c}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              )}
              <span className="text-xs text-gray-500">
                {t("openInNewTab")}
              </span>
            </span>
          ) : null}
        </div>
      ) : null}

      {schemaCollections.length === 0 && availableCollections.length === 0 ? (
        <p className="text-xs text-amber-600">
          {t("noCollection", {
            collectionCode: "items.collection",
            collectionsCode: "items.collections",
          })}
        </p>
      ) : null}

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