"use client";

import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { AlertTriangle, Bot, Loader2, X } from "lucide-react";
import { adminApi, aiApi } from "@/lib/api/client";
import { tToast } from "@/lib/utils/translated-toast";

type Field = "TITLE" | "ABSTRACT" | "KEYWORDS";

interface Suggestion {
  readable: boolean;
  noteHi: string | null;
  noteEn: string | null;
  currentTitleHi: string | null;
  currentTitleEn: string | null;
  currentAbstractHi: string | null;
  currentAbstractEn: string | null;
  currentKeywords: string[] | null;
  titleHi: string | null;
  titleEn: string | null;
  abstractHi: string | null;
  abstractEn: string | null;
  keywords: string[] | null;
  abstractWordsHi: number | null;
  abstractWordsEn: number | null;
  charactersRead: number;
  truncated: boolean;
  updatedAt: string | null;
}

const FIELDS: { value: Field; hi: string; en: string }[] = [
  { value: "TITLE", hi: "शीर्षक", en: "Title" },
  { value: "ABSTRACT", hi: "सार", en: "Abstract" },
  { value: "KEYWORDS", hi: "कीवर्ड", en: "Keywords" },
];

export function AdminMetadataModal({
  open,
  onClose,
  paperId,
  paperReferenceNo,
}: {
  open: boolean;
  onClose: () => void;
  paperId: string | null;
  paperReferenceNo: string | null;
}) {
  const queryClient = useQueryClient();
  const [fields, setFields] = useState<Field[]>(["TITLE", "ABSTRACT", "KEYWORDS"]);
  const [maxWords, setMaxWords] = useState(250);
  const [result, setResult] = useState<Suggestion | null>(null);
  // Which generated fields the editor still wants. Defaulted on: if they asked
  // for an abstract, they want the abstract — this is for dropping one that
  // came back worse than what the author wrote.
  const [accepted, setAccepted] = useState<Record<Field, boolean>>({
    TITLE: true,
    ABSTRACT: true,
    KEYWORDS: true,
  });

  const { data: aiStatus } = useQuery({
    queryKey: ["ai-status"],
    queryFn: async () => (await aiApi.status()).data,
    staleTime: Infinity,
    retry: false,
  });
  const aiAvailable = aiStatus?.configured === true;

  function reset() {
    setResult(null);
    setFields(["TITLE", "ABSTRACT", "KEYWORDS"]);
    setMaxWords(250);
    setAccepted({ TITLE: true, ABSTRACT: true, KEYWORDS: true });
  }

  function close() {
    reset();
    onClose();
  }

  const generate = useMutation({
    mutationFn: () =>
      adminApi.generatePaperMetadata(paperId!, { fields, abstractMaxWords: maxWords }),
    onSuccess: (res) => setResult(res.data as Suggestion),
    onError: (err: { response?: { status?: number; data?: { message?: string } } }) => {
      const status = err?.response?.status;
      // Mirrors the submit form's mapping — these are the codes the backend
      // actually emits, and "try again later" is wrong advice for both.
      if (status === 429) {
        tToast("error", "ai.rate_limited", "बहुत अधिक AI अनुरोध / Too many AI requests — please wait");
      } else if (status === 503) {
        tToast("error", "ai.unavailable", "एआई सेवा उपलब्ध नहीं है / The AI service is unavailable");
      } else {
        tToast("error", "ai.failed", err?.response?.data?.message ?? "Could not generate");
      }
    },
  });

  const apply = useMutation({
    mutationFn: () => {
      const body: Record<string, unknown> = { expectedUpdatedAt: result?.updatedAt };
      if (fields.includes("TITLE") && accepted.TITLE) {
        body.titleHi = result?.titleHi;
        body.titleEn = result?.titleEn;
      }
      if (fields.includes("ABSTRACT") && accepted.ABSTRACT) {
        body.abstractHi = result?.abstractHi;
        body.abstractEn = result?.abstractEn;
      }
      if (fields.includes("KEYWORDS") && accepted.KEYWORDS) {
        body.keywords = result?.keywords;
      }
      return adminApi.updatePaperMetadata(paperId!, body);
    },
    onSuccess: () => {
      tToast("success", "admin_papers.metadata_saved", "Paper details updated");
      queryClient.invalidateQueries({ queryKey: ["admin-papers"] });
      close();
    },
    onError: (err: { response?: { data?: { message?: string } } }) =>
      tToast("error", "admin_papers.metadata_save_failed",
        err?.response?.data?.message ?? "Could not save"),
  });

  if (!open || !paperId) return null;

  const nothingAccepted =
    !!result &&
    fields.every((f) => !accepted[f]);

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
      <div className="max-h-[88vh] w-full max-w-3xl overflow-y-auto rounded-xl bg-white p-6 shadow-xl">
        <div className="mb-4 flex items-start justify-between">
          <div>
            <h3 className="flex items-center gap-2 text-base font-semibold text-gray-900">
              <Bot className="h-4 w-4 text-indigo-600" />
              AI से विवरण बनवाएँ / Generate details with AI
            </h3>
            <p className="mt-0.5 text-xs text-gray-500">{paperReferenceNo}</p>
          </div>
          <button onClick={close} className="text-gray-400 hover:text-gray-600">
            <X className="h-4 w-4" />
          </button>
        </div>

        {!aiAvailable && (
          <p className="rounded-lg bg-amber-50 p-3 text-xs text-amber-900">
            एआई सेवा कॉन्फ़िगर नहीं है।
            <br />
            The AI service is not configured on this instance.
          </p>
        )}

        {/* Step 1 — pick */}
        {!result && aiAvailable && (
          <>
            <p className="mb-4 text-xs text-gray-500">
              AI पूरी पांडुलिपि पढ़कर सुझाव देगा। कुछ भी अपने आप सहेजा नहीं जाएगा।
              <br />
              AI reads the manuscript and proposes wording. Nothing is saved until you choose to.
            </p>

            <div className="space-y-2">
              {FIELDS.map((f) => (
                <label key={f.value} className="flex cursor-pointer items-center gap-2.5">
                  <input
                    type="checkbox"
                    checked={fields.includes(f.value)}
                    onChange={(e) =>
                      setFields((prev) =>
                        e.target.checked ? [...prev, f.value] : prev.filter((x) => x !== f.value),
                      )
                    }
                    className="h-4 w-4 rounded border-gray-300 text-indigo-600"
                  />
                  <span className="text-sm text-gray-800">
                    {f.hi} / {f.en}
                  </span>
                </label>
              ))}
            </div>

            {fields.includes("ABSTRACT") && (
              <div className="mt-4">
                <label className="block text-xs font-medium text-gray-700">
                  सार की अधिकतम लंबाई / Maximum abstract length
                </label>
                <div className="mt-1.5 flex items-center gap-2">
                  <input
                    type="number"
                    min={40}
                    max={600}
                    value={maxWords}
                    onChange={(e) => setMaxWords(Number(e.target.value))}
                    className="w-24 rounded-lg border border-gray-300 px-3 py-1.5 text-sm"
                  />
                  <span className="text-xs text-gray-500">शब्द / words</span>
                </div>
              </div>
            )}

            <p className="mt-4 text-xs text-gray-400">
              इसमें एक मिनट तक लग सकता है।
              <br />
              This can take up to a minute — the whole manuscript is being read.
            </p>

            <div className="mt-6 flex justify-end gap-2 border-t border-gray-100 pt-4">
              <button
                onClick={close}
                className="rounded-lg border border-gray-300 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50"
              >
                रद्द करें / Cancel
              </button>
              <button
                onClick={() => generate.mutate()}
                disabled={fields.length === 0 || generate.isPending}
                className="inline-flex items-center gap-2 rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:opacity-50"
              >
                {generate.isPending ? (
                  <Loader2 className="h-3.5 w-3.5 animate-spin" />
                ) : (
                  <Bot className="h-3.5 w-3.5" />
                )}
                बनाएँ / Generate
              </button>
            </div>
          </>
        )}

        {/* Step 2 — review */}
        {result && !result.readable && (
          <>
            <div className="flex gap-3 rounded-lg bg-amber-50 p-4">
              <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-600" />
              <div className="text-xs text-amber-900">
                <p className="font-medium">
                  पांडुलिपि पढ़ी नहीं जा सकी / The manuscript could not be read
                </p>
                <p className="mt-1">{result.noteHi}</p>
                <p>{result.noteEn}</p>
                <p className="mt-2 text-amber-700">
                  यह स्कैन की गई छवि या पुराने (नॉन-यूनिकोड) हिंदी फ़ॉन्ट में हो सकती है।
                  <br />
                  It may be a scanned image, or Hindi typed in an older non-Unicode font.
                </p>
              </div>
            </div>
            <div className="mt-6 flex justify-end border-t border-gray-100 pt-4">
              <button
                onClick={close}
                className="rounded-lg border border-gray-300 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50"
              >
                बंद करें / Close
              </button>
            </div>
          </>
        )}

        {result && result.readable && (
          <>
            <p className="mb-4 text-xs text-gray-500">
              {result.charactersRead.toLocaleString()} अक्षर पढ़े गए
              {result.truncated ? " (पांडुलिपि का आरंभिक भाग)" : ""} /{" "}
              {result.charactersRead.toLocaleString()} characters read
              {result.truncated ? " (the opening of the manuscript)" : ""}
            </p>

            <div className="space-y-5">
              {fields.includes("TITLE") && (
                <Compare
                  label="शीर्षक / Title"
                  accepted={accepted.TITLE}
                  onToggle={(v) => setAccepted((a) => ({ ...a, TITLE: v }))}
                  rows={[
                    { lang: "हिन्दी", before: result.currentTitleHi, after: result.titleHi },
                    { lang: "English", before: result.currentTitleEn, after: result.titleEn },
                  ]}
                />
              )}
              {fields.includes("ABSTRACT") && (
                <Compare
                  label="सार / Abstract"
                  accepted={accepted.ABSTRACT}
                  onToggle={(v) => setAccepted((a) => ({ ...a, ABSTRACT: v }))}
                  note={wordNote(result, maxWords)}
                  rows={[
                    { lang: "हिन्दी", before: result.currentAbstractHi, after: result.abstractHi },
                    { lang: "English", before: result.currentAbstractEn, after: result.abstractEn },
                  ]}
                />
              )}
              {fields.includes("KEYWORDS") && (
                <Compare
                  label="कीवर्ड / Keywords"
                  accepted={accepted.KEYWORDS}
                  onToggle={(v) => setAccepted((a) => ({ ...a, KEYWORDS: v }))}
                  rows={[
                    {
                      lang: "—",
                      before: (result.currentKeywords ?? []).join(", "),
                      after: (result.keywords ?? []).join(", "),
                    },
                  ]}
                />
              )}
            </div>

            <div className="mt-6 flex justify-end gap-2 border-t border-gray-100 pt-4">
              <button
                onClick={() => setResult(null)}
                className="rounded-lg border border-gray-300 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50"
              >
                फिर से / Start over
              </button>
              <button
                onClick={() => apply.mutate()}
                disabled={nothingAccepted || apply.isPending}
                className="inline-flex items-center gap-2 rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:opacity-50"
              >
                {apply.isPending && <Loader2 className="h-3.5 w-3.5 animate-spin" />}
                चुने हुए सहेजें / Save selected
              </button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

/** The cap is advisory, so an overshoot is shown rather than silently trimmed. */
function wordNote(result: Suggestion, cap: number): string | undefined {
  const hi = result.abstractWordsHi;
  const en = result.abstractWordsEn;
  if (hi == null && en == null) return undefined;
  const over = (hi ?? 0) > cap || (en ?? 0) > cap;
  return `${hi ?? "–"} / ${en ?? "–"} शब्द, सीमा ${cap} words (limit ${cap})${over ? " — over" : ""}`;
}

function Compare({
  label,
  rows,
  accepted,
  onToggle,
  note,
}: {
  label: string;
  rows: { lang: string; before: string | null; after: string | null }[];
  accepted: boolean;
  onToggle: (v: boolean) => void;
  note?: string;
}) {
  return (
    <div className="rounded-lg border border-gray-200">
      <div className="flex items-center justify-between border-b border-gray-100 bg-gray-50 px-4 py-2">
        <span className="text-xs font-semibold text-gray-700">{label}</span>
        <label className="flex cursor-pointer items-center gap-2 text-xs text-gray-600">
          <input
            type="checkbox"
            checked={accepted}
            onChange={(e) => onToggle(e.target.checked)}
            className="h-3.5 w-3.5 rounded border-gray-300 text-indigo-600"
          />
          इसे लें / Use this
        </label>
      </div>
      {note && <p className="border-b border-gray-100 px-4 py-1.5 text-[11px] text-gray-500">{note}</p>}
      {rows.map((row) => (
        <div key={row.lang} className="grid grid-cols-2 gap-4 border-b border-gray-50 px-4 py-3 last:border-0">
          <div>
            <p className="mb-1 text-[10px] uppercase tracking-wide text-gray-400">
              अभी / Now · {row.lang}
            </p>
            <p className="whitespace-pre-wrap text-xs text-gray-500">{row.before || "—"}</p>
          </div>
          <div>
            <p className="mb-1 text-[10px] uppercase tracking-wide text-indigo-400">
              सुझाव / Suggested · {row.lang}
            </p>
            <p className={`whitespace-pre-wrap text-xs ${accepted ? "text-gray-900" : "text-gray-400 line-through"}`}>
              {row.after || "—"}
            </p>
          </div>
        </div>
      ))}
    </div>
  );
}
