// src/components/keywords/related-keywords-dialog.tsx — dialog PARTAGÉ « Mots-clés
// associés » (Réservoir + Recherche). Seed = terme d'un mot-clé ; à l'ouverture,
// appelle `getRelatedKeywordsAction` (KWFinder related, DÉJÀ enrichis). Tableau
// checkbox/terme/volume/KD/CPC dans l'ORDRE API (= pertinence), filtre texte
// LOCAL, « tout cocher », footer : compteur + « Ajouter au Réservoir » / « Envoyer
// en Recherche ». États : loading, vide, erreurs (quota → message doux ;
// no_connector → CTA « Connecter Mangools »). Responsive : DialogContent
// sm:max-w-2xl, liste scrollable max-h-[50dvh] (leçon des dialogs récents).
"use client";

import { SearchIcon, SparklesIcon } from "lucide-react";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { useEffect, useMemo, useRef, useState, useTransition } from "react";
import { toast } from "sonner";
import { QuotaNotice } from "@/components/billing/quota-notice";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton";
import type { QuotaExceeded } from "@/lib/billing/quotas";
import {
  addRelatedKeywordsAction,
  getRelatedKeywordsAction,
} from "@/lib/mangools/related-actions";
import type { RelatedRow } from "@/lib/mangools/related-core";

/** Bouton de toolbar « Mots-clés associés » (slot `relatedButton` des toolbars
 *  Réservoir/Recherche). Encapsule le label i18n + l'icône Sparkles pour que les
 *  containers n'aient pas à importer Button/lucide/i18n. Le container décide de
 *  le rendre (connecteur Mangools branché) et de l'activer (1 kw sélectionné). */
export function RelatedKeywordsButton({
  disabled,
  onClick,
}: {
  disabled?: boolean;
  onClick: () => void;
}) {
  const t = useTranslations("Keywords.related");
  return (
    <Button
      variant="outline"
      className="h-10 rounded-[11px] text-muted-foreground hover:text-foreground"
      disabled={disabled}
      onClick={onClick}
    >
      <SparklesIcon className="size-4" aria-hidden />
      {t("trigger")}
    </Button>
  );
}

type LoadState =
  | { status: "loading" }
  | { status: "ready"; rows: RelatedRow[] }
  | {
      status: "error";
      error: "no_connector" | "no_location" | "quota" | "upstream";
    };

/** Formate une métrique optionnelle : `null` → « — ». */
function fmt(v: number | null): string {
  if (v == null) return "—";
  return v.toLocaleString();
}

export function RelatedKeywordsDialog({
  open,
  onOpenChange,
  siteId,
  seedTerm,
  onAdded,
}: {
  open: boolean;
  onOpenChange: (o: boolean) => void;
  siteId: string;
  /** Terme du mot-clé source (seed KWFinder). `null` = pas de seed (dialog fermé). */
  seedTerm: string | null;
  /** Appelé après un ajout réussi — le container recâble sur son `refresh()`. */
  onAdded?: () => void;
}) {
  const t = useTranslations("Keywords.related");
  const [state, setState] = useState<LoadState>({ status: "loading" });
  const [filter, setFilter] = useState("");
  // Sélection par TERME (clé naturelle, stable au filtrage).
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [adding, startAdd] = useTransition();
  // Quota dépassé au moment d'ajouter : rendu inline via <QuotaNotice> (message
  // localisé + CTA upgrade), pas un toast anglais brut.
  const [quota, setQuota] = useState<QuotaExceeded | null>(null);
  const wasOpenRef = useRef(false);

  // Ouverture (closed→open) : reset + fetch. Fermeture : reset propre pour ne
  // pas flasher des résultats périmés au prochain open.
  useEffect(() => {
    const wasOpen = wasOpenRef.current;
    wasOpenRef.current = open;
    if (open && !wasOpen && seedTerm) {
      setState({ status: "loading" });
      setFilter("");
      setSelected(new Set());
      setQuota(null);
      let cancelled = false;
      getRelatedKeywordsAction(siteId, seedTerm)
        .then((res) => {
          if (cancelled) return;
          if (res.ok) setState({ status: "ready", rows: res.rows });
          else setState({ status: "error", error: res.error });
        })
        .catch(() => {
          if (!cancelled) setState({ status: "error", error: "upstream" });
        });
      return () => {
        cancelled = true;
      };
    }
    if (!open) {
      setFilter("");
      setSelected(new Set());
      setQuota(null);
    }
  }, [open, seedTerm, siteId]);

  const rows = state.status === "ready" ? state.rows : [];
  const filtered = useMemo(() => {
    const q = filter.trim().toLowerCase();
    if (!q) return rows;
    return rows.filter((r) => r.term.toLowerCase().includes(q));
  }, [rows, filter]);

  const allVisibleChecked =
    filtered.length > 0 && filtered.every((r) => selected.has(r.term));

  function toggleAll() {
    setSelected((prev) => {
      const next = new Set(prev);
      if (allVisibleChecked) {
        for (const r of filtered) next.delete(r.term);
      } else {
        for (const r of filtered) next.add(r.term);
      }
      return next;
    });
  }

  function toggleOne(term: string) {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(term)) next.delete(term);
      else next.add(term);
      return next;
    });
  }

  function add(destination: "reservoir" | "recherche") {
    const picked = rows.filter((r) => selected.has(r.term));
    if (picked.length === 0) return;
    setQuota(null);
    startAdd(async () => {
      try {
        const res = await addRelatedKeywordsAction(siteId, picked, destination);
        if (!res.ok) {
          // Quota → notice inline localisée ; autre erreur → toast.
          if (res.quota) setQuota(res.quota);
          else toast.error(res.error || t("addError"));
          return;
        }
        // Toast honnête : « N ajoutés » quand tout est neuf ; « N ajoutés,
        // M déjà présents mis à jour » quand un re-add a mergé des existants.
        toast.success(
          res.updated > 0
            ? t("addSuccessPartial", { added: res.added, updated: res.updated })
            : t("addSuccess", { count: res.added }),
        );
        onAdded?.();
        onOpenChange(false);
      } catch {
        toast.error(t("addError"));
      }
    });
  }

  const selectedCount = selected.size;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-2xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <SparklesIcon
              className="size-4 text-muted-foreground"
              aria-hidden
            />
            {t("title")}
          </DialogTitle>
          <DialogDescription>
            {t("description", { seed: seedTerm ?? "" })}
          </DialogDescription>
        </DialogHeader>

        {/* Loading */}
        {state.status === "loading" ? (
          <div className="grid gap-2 py-2">
            {Array.from({ length: 6 }, (_, i) => (
              // biome-ignore lint/suspicious/noArrayIndexKey: static skeleton rows
              <Skeleton key={i} className="h-9 w-full rounded-md" />
            ))}
          </div>
        ) : null}

        {/* Erreur no_connector : CTA « Connecter Mangools ». */}
        {state.status === "error" && state.error === "no_connector" ? (
          <div className="grid place-items-center gap-3 py-10 text-center">
            <p className="text-muted-foreground text-sm">
              {t("noConnectorText")}
            </p>
            <Button asChild>
              <Link href="/settings/integrations">{t("noConnectorCta")}</Link>
            </Button>
          </div>
        ) : null}

        {/* Autres erreurs : message doux, pas de blocage dur. */}
        {state.status === "error" && state.error !== "no_connector" ? (
          <div className="py-10 text-center text-muted-foreground text-sm">
            {state.error === "quota"
              ? t("errorQuota")
              : state.error === "no_location"
                ? t("errorLocation")
                : t("errorUpstream")}
          </div>
        ) : null}

        {/* Prêt : filtre + tableau + footer. */}
        {state.status === "ready" ? (
          <>
            <div className="relative">
              <SearchIcon
                className="-translate-y-1/2 absolute top-1/2 left-2.5 size-4 text-muted-foreground"
                aria-hidden
              />
              <Input
                value={filter}
                onChange={(e) => setFilter(e.target.value)}
                placeholder={t("searchPlaceholder")}
                aria-label={t("searchPlaceholder")}
                className="pl-8"
              />
            </div>

            {filtered.length === 0 ? (
              <div className="py-10 text-center text-muted-foreground text-sm">
                {t("empty")}
              </div>
            ) : (
              <div className="max-h-[50dvh] overflow-y-auto rounded-md border">
                <table className="w-full text-sm">
                  <thead className="sticky top-0 z-10 bg-card">
                    <tr className="border-b text-left text-muted-foreground text-xs">
                      <th className="w-9 px-2 py-2">
                        <Checkbox
                          checked={allVisibleChecked}
                          onCheckedChange={toggleAll}
                          aria-label={t("selectAll")}
                        />
                      </th>
                      <th className="px-2 py-2 font-medium">{t("colTerm")}</th>
                      <th className="px-2 py-2 text-right font-medium">
                        {t("colVolume")}
                      </th>
                      <th className="px-2 py-2 text-right font-medium">
                        {t("colKd")}
                      </th>
                      <th className="px-2 py-2 text-right font-medium">
                        {t("colCpc")}
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    {filtered.map((r) => {
                      const checked = selected.has(r.term);
                      return (
                        <tr
                          key={r.term}
                          className="border-b last:border-0 hover:bg-accent/40"
                        >
                          <td className="px-2 py-1.5">
                            <Checkbox
                              checked={checked}
                              onCheckedChange={() => toggleOne(r.term)}
                              aria-label={r.term}
                            />
                          </td>
                          <td className="max-w-[22rem] truncate px-2 py-1.5">
                            <button
                              type="button"
                              className="truncate text-left align-middle"
                              title={r.term}
                              onClick={() => toggleOne(r.term)}
                            >
                              {r.term}
                            </button>
                          </td>
                          <td className="px-2 py-1.5 text-right tabular-nums">
                            {fmt(r.volume)}
                          </td>
                          <td className="px-2 py-1.5 text-right tabular-nums">
                            {fmt(r.kd)}
                          </td>
                          <td className="px-2 py-1.5 text-right tabular-nums">
                            {fmt(r.cpc)}
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}

            {quota ? <QuotaNotice quota={quota} /> : null}

            <DialogFooter className="items-center gap-2 sm:justify-between">
              <span className="text-muted-foreground text-sm">
                {t("selected", { count: selectedCount })}
              </span>
              <div className="flex items-center gap-2">
                <Button
                  variant="outline"
                  disabled={selectedCount === 0 || adding}
                  onClick={() => add("reservoir")}
                >
                  {t("addReservoir")}
                </Button>
                <Button
                  disabled={selectedCount === 0 || adding}
                  onClick={() => add("recherche")}
                >
                  {t("addRecherche")}
                </Button>
              </div>
            </DialogFooter>
          </>
        ) : null}
      </DialogContent>
    </Dialog>
  );
}
