import {useState} from "react";
import {ArrayOfObjectsInputProps, PatchEvent, set, useClient} from "sanity";

type ThemeReference = {
  _type: "reference";
  _ref: string;
  _key: string;
};

const API_VERSION = "2026-03-26";

function buildThemeReference(themeId: string): ThemeReference {
  return {
    _type: "reference",
    _ref: themeId,
    _key: `theme-${themeId}`.slice(0, 120),
  };
}

type ThemeSet = {
  type: "theme" | "tonieboxTheme";
  label: string;
  resultLabel: string;
};

type ThemeAction = "add" | "remove";

const THEME_SETS: ThemeSet[] = [
  {type: "theme", label: "themes", resultLabel: "theme(s)"},
  {type: "tonieboxTheme", label: "themes Toniebox", resultLabel: "theme(s) Toniebox"},
];

function isThemeReference(item: unknown): item is ThemeReference {
  return Boolean(item) && typeof item === "object" && "_ref" in (item as object) && typeof (item as ThemeReference)._ref === "string";
}

function ActionButton({
  label,
  disabled,
  onClick,
}: {
  label: string;
  disabled: boolean;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      disabled={disabled}
      onClick={onClick}
      style={{
        appearance: "none",
        border: "1px solid currentColor",
        borderRadius: 3,
        background: "transparent",
        color: "inherit",
        cursor: disabled ? "not-allowed" : "pointer",
        font: "inherit",
        fontWeight: 600,
        padding: "8px 12px",
        opacity: disabled ? 0.5 : 1,
      }}
    >
      {label}
    </button>
  );
}

export function AllThemesInput(props: ArrayOfObjectsInputProps) {
  const client = useClient({apiVersion: API_VERSION});
  const [loadingKey, setLoadingKey] = useState<string | null>(null);
  const [message, setMessage] = useState("");
  const isDisabled = props.readOnly || loadingKey !== null;
  const existingReferences = (props.value || []).filter(isThemeReference);

  const addAllThemes = async (themeSet: ThemeSet) => {
    const themeIds = await client.fetch<string[]>(
      `*[_type == $type && coalesce(isActive, true) == true] | order(lower(title) asc)._id`,
      {type: themeSet.type},
    );
    const referencesById = new Map(existingReferences.map((reference) => [reference._ref, reference]));

    for (const themeId of themeIds) {
      if (!referencesById.has(themeId)) {
        referencesById.set(themeId, buildThemeReference(themeId));
      }
    }

    props.onChange(PatchEvent.from(set(Array.from(referencesById.values()))));
    setMessage(`${themeIds.length} ${themeSet.resultLabel} actif(s) ajoute(s).`);
  };

  const removeAllThemes = async (themeSet: ThemeSet) => {
    const referencedIds = existingReferences.map((reference) => reference._ref);
    const matchingIds = await client.fetch<string[]>(
      `*[_type == $type && (_id in $ids || _id in $draftIds)]._id`,
      {type: themeSet.type, ids: referencedIds, draftIds: referencedIds.map((id) => `drafts.${id}`)},
    );
    const idsToRemove = new Set(matchingIds.map((id) => id.replace(/^drafts\./, "")));

    if (!idsToRemove.size) {
      setMessage(`Aucun ${themeSet.resultLabel} a retirer.`);
      return;
    }

    if (!window.confirm(`Retirer ${idsToRemove.size} ${themeSet.resultLabel} de ce produit ?`)) {
      return;
    }

    const nextValue = (props.value || []).filter((item) => !isThemeReference(item) || !idsToRemove.has(item._ref));
    props.onChange(PatchEvent.from(set(nextValue)));
    setMessage(`${idsToRemove.size} ${themeSet.resultLabel} retire(s).`);
  };

  const runAction = async (action: ThemeAction, themeSet: ThemeSet) => {
    setLoadingKey(`${action}-${themeSet.type}`);
    setMessage("");

    try {
      await (action === "add" ? addAllThemes(themeSet) : removeAllThemes(themeSet));
    } catch (error) {
      console.error(`Unable to ${action} themes`, error);
      setMessage("Impossible de charger les themes. Reessayez.");
    } finally {
      setLoadingKey(null);
    }
  };

  return (
    <div style={{display: "grid", gap: 12}}>
      {THEME_SETS.map((themeSet) => (
        <div key={themeSet.type} style={{display: "flex", alignItems: "center", flexWrap: "wrap", gap: 12}}>
          <ActionButton
            label={loadingKey === `add-${themeSet.type}` ? "Ajout en cours..." : `Ajouter tous les ${themeSet.label}`}
            disabled={isDisabled}
            onClick={() => runAction("add", themeSet)}
          />
          <ActionButton
            label={loadingKey === `remove-${themeSet.type}` ? "Suppression en cours..." : `Retirer tous les ${themeSet.label}`}
            disabled={isDisabled || !existingReferences.length}
            onClick={() => runAction("remove", themeSet)}
          />
        </div>
      ))}
      {message ? <span style={{fontSize: 13}}>{message}</span> : null}
      {props.renderDefault(props)}
    </div>
  );
}
