"use client";

import { useEffect, useRef, useState, useTransition } from "react";
import { Button } from "@/components/ui";
import { Field, inputClass } from "@/components/ui/form";
import { saveCategoryAction } from "@/lib/actions/categories";
import { LOCALES } from "@/lib/i18n/catalog";

export interface CategoryDraft { id?: string; parentId?: string | null; isGroup: boolean; code: string; labels: Record<string, string>; selectable: boolean }
export interface Language { locale: string; isDefault: boolean }

/** Add / edit a category: code, a label per language (the default language is the category's name) and whether entries can pick it. */
export function CategoryDialog({ siteId, draft, languages, title, onClose, onSaved }: { siteId: string; draft: CategoryDraft | null; languages: Language[]; title: string; onClose: () => void; onSaved: () => void }) {
  const ref = useRef<HTMLDialogElement>(null);
  const [v, setV] = useState<CategoryDraft | null>(draft);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [error, setError] = useState<string | null>(null);
  const [pending, start] = useTransition();
  const def = languages.find((l) => l.isDefault)?.locale ?? languages[0]?.locale ?? "en-GB";

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect -- reset the form whenever a different draft opens
    setV(draft); setErrors({}); setError(null);
    const d = ref.current;
    if (!d) return;
    if (draft && !d.open) d.showModal();
    if (!draft && d.open) d.close();
  }, [draft]);

  function submit() {
    if (!v) return;
    setErrors({}); setError(null);
    start(async () => {
      const r = await saveCategoryAction(siteId, { id: v.id, parentId: v.parentId ?? null, isGroup: v.isGroup, code: v.code, name: v.labels[def] ?? "", labels: v.labels, selectable: v.selectable });
      if (r.ok) onSaved();
      else { setErrors(Object.fromEntries(Object.entries(r.fieldErrors ?? {}).map(([k, m]) => [k.replace(/^labels\./, "label-"), m]))); setError(r.error); }
    });
  }

  return (
    <dialog ref={ref} onClose={onClose} aria-labelledby="cat-dlg-title" className="m-auto w-[min(32rem,92vw)] rounded-lg border border-border bg-card p-5 text-foreground backdrop:bg-black/40">
      {v ? (
        <form onSubmit={(e) => { e.preventDefault(); submit(); }} className="space-y-4">
          <h2 id="cat-dlg-title" className="text-base font-semibold">{title}</h2>
          <Field id="cat-code" label="Code" help="Optional short code, for example BE." error={errors["code"]}>
            <input id="cat-code" className={inputClass} maxLength={40} value={v.code} onChange={(e) => setV({ ...v, code: e.target.value })} aria-describedby="cat-code-help" />
          </Field>
          <fieldset className="space-y-3">
            <legend className="text-sm font-medium">Labels</legend>
            {languages.map((l) => (
              <Field key={l.locale} id={`cat-label-${l.locale}`} label={`${LOCALES[l.locale] ?? l.locale}${l.isDefault ? " (default)" : ""}`} error={l.isDefault ? errors["name"] : errors[`label-${l.locale}`]}>
                <input id={`cat-label-${l.locale}`} className={inputClass} maxLength={80} required={l.isDefault} value={v.labels[l.locale] ?? ""} onChange={(e) => setV({ ...v, labels: { ...v.labels, [l.locale]: e.target.value } })} />
              </Field>
            ))}
          </fieldset>
          {!v.isGroup ? <label className="flex items-center gap-2 text-sm"><input type="checkbox" checked={v.selectable} onChange={(e) => setV({ ...v, selectable: e.target.checked })} />Category selectable <span className="text-xs text-muted-foreground">(entries can pick it)</span></label> : null}
          {error && Object.keys(errors).length === 0 ? <p role="alert" className="text-sm text-danger">{error}</p> : null}
          <div className="flex justify-end gap-2">
            <Button variant="secondary" onClick={onClose}>Cancel</Button>
            <Button type="submit" disabled={pending}>{pending ? "Saving…" : "Save category"}</Button>
          </div>
        </form>
      ) : null}
    </dialog>
  );
}
