// src/components/keywords/keyword-picker-dialog.tsx — dialog générique
// « choisis un mot-clé du site » : input de recherche (debounce 250ms) →
// fetchKeywordsPageAction (limit 20, filtre texte `q`), liste term + drapeau
// pays, clic → onSelect puis fermeture. Réutilisé par SourcesModal pour
// rattacher un import SERP ou un brief YTG à un mot-clé existant quand
// l'auto-détection par nom échoue.
"use client";

import { SearchIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Flag } from "@/components/ui/flag";
import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton";
import { fetchKeywordsPageAction } from "@/lib/keywords/actions";
import type { Keyword } from "@/lib/keywords/types";

const PAGE_LIMIT = 20;
const DEBOUNCE_MS = 250;

export function KeywordPickerDialog({
  open,
  onOpenChange,
  siteId,
  title,
  description,
  onSelect,
  initialQuery,
}: {
  open: boolean;
  onOpenChange: (o: boolean) => void;
  siteId: string;
  title: string;
  description?: string;
  onSelect: (kw: { id: string; term: string; country: string }) => void;
  /** Pré-remplit la recherche à l'ouverture (transition fermé→ouvert) et
   *  déclenche immédiatement la recherche avec cette valeur — utilisé quand
   *  un appelant a déjà une intuition du mot-clé cible (ex. nom de fichier
   *  détecté mais non résolu automatiquement). Ignoré si absent. */
  initialQuery?: string;
}) {
  const [queryInput, setQueryInput] = useState("");
  const [query, setQuery] = useState("");
  const [loading, setLoading] = useState(false);
  const [rows, setRows] = useState<Keyword[]>([]);
  // Tracks the previous `open` value so the pre-fill below only fires on an
  // actual closed→open transition — not on every `initialQuery` change while
  // the dialog stays open (which would fight the user's own typing).
  const wasOpenRef = useRef(open);

  // On open: pre-fill from `initialQuery` (or blank) and trigger the search
  // immediately (bypass debounce) so results show without waiting 250ms.
  // On close: reset to a clean slate so the next open doesn't flash stale
  // results before the first fetch. The open-transition branch below always
  // wins over any stale close-reset, so there's no race between the two.
  useEffect(() => {
    const wasOpen = wasOpenRef.current;
    wasOpenRef.current = open;
    if (open && !wasOpen) {
      setQueryInput(initialQuery ?? "");
      setQuery(initialQuery ?? "");
    } else if (!open) {
      setQueryInput("");
      setQuery("");
      setRows([]);
    }
  }, [open, initialQuery]);

  // Debounce the search box: the field updates instantly for a responsive
  // typing feel, the committed (fetch-triggering) value follows 250ms later.
  useEffect(() => {
    const t = setTimeout(() => setQuery(queryInput), DEBOUNCE_MS);
    return () => clearTimeout(t);
  }, [queryInput]);

  useEffect(() => {
    if (!open) return;
    let cancelled = false;
    setLoading(true);
    fetchKeywordsPageAction(siteId, {
      filter: { q: query },
      sort: { field: "term", desc: false },
      limit: PAGE_LIMIT,
    })
      .then((page) => {
        if (!cancelled) setRows(page.rows);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [open, siteId, query]);

  function pick(kw: Keyword) {
    onSelect({ id: kw.id, term: kw.term, country: kw.locale.country });
    onOpenChange(false);
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          {description ? (
            <DialogDescription>{description}</DialogDescription>
          ) : null}
        </DialogHeader>

        <div className="grid gap-3">
          <div className="relative">
            <SearchIcon
              className="-translate-y-1/2 absolute top-1/2 left-2.5 size-4 text-muted-foreground"
              aria-hidden
            />
            <Input
              autoFocus
              value={queryInput}
              onChange={(e) => setQueryInput(e.target.value)}
              placeholder="Rechercher un mot-clé…"
              aria-label="Rechercher un mot-clé"
              className="pl-8"
            />
          </div>

          <ul className="grid max-h-72 gap-0.5 overflow-y-auto">
            {loading
              ? Array.from({ length: 5 }, (_, i) => (
                  // biome-ignore lint/suspicious/noArrayIndexKey: static skeleton rows, no reorder
                  <li key={i}>
                    <Skeleton className="h-9 w-full rounded-md" />
                  </li>
                ))
              : null}

            {!loading && rows.length === 0 ? (
              <li className="px-2 py-6 text-center text-muted-foreground text-sm">
                Aucun mot-clé trouvé.
              </li>
            ) : null}

            {!loading
              ? rows.map((kw) => (
                  <li key={kw.id}>
                    <button
                      type="button"
                      onClick={() => pick(kw)}
                      className="flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-sm hover:bg-accent"
                    >
                      <Flag code={kw.locale.country} />
                      <span className="truncate">{kw.term}</span>
                    </button>
                  </li>
                ))
              : null}
          </ul>
        </div>
      </DialogContent>
    </Dialog>
  );
}
