// src/components/keywords/target-page-cell.tsx — cellule « Page ciblée » du
// réservoir (module Pages). Affiche le path court de la page assignée + un badge
// coloré par source du signal de mapping (gsc > content > text > manual), avec
// l'URL complète en tooltip. Le clic ouvre un picker (popover) : recherche
// debouncée (`searchSitePagesAction`) → assignation manuelle
// (`setKeywordTargetPageAction`, source 'manual') ou retrait (page → null, le
// mot-clé redevient auto-mappable). Rendu par ligne dans la table du réservoir.
"use client";

import { LinkIcon, SearchIcon, XIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { useEffect, useState, useTransition } from "react";
import { toast } from "sonner";
import { Input } from "@/components/ui/input";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import type { Keyword } from "@/lib/keywords/types";
import {
  searchSitePagesAction,
  setKeywordTargetPageAction,
} from "@/lib/pages/actions";
import { cn } from "@/lib/utils";

type TargetSource = NonNullable<Keyword["targetPage"]>["source"];

type SitePageOption = { id: string; url: string; title: string | null };

/** Path court affiché dans la cellule : dernier segment du pathname (préfixé
 *  « / »), sinon le hostname pour une racine. L'URL complète vit dans le
 *  tooltip. Une URL non parsable retombe sur la chaîne brute. */
function shortPath(url: string): string {
  try {
    const u = new URL(url);
    const path = u.pathname.replace(/\/+$/, "");
    if (!path) return u.hostname;
    const segs = path.split("/").filter(Boolean);
    return segs.length > 0 ? `/${segs[segs.length - 1]}` : u.hostname;
  } catch {
    return url;
  }
}

/** Classes du badge source (pastille pill @10% fond / @30% bord). */
const SOURCE_BADGE: Record<TargetSource, string> = {
  gsc: "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300",
  content: "border-blue-500/30 bg-blue-500/10 text-blue-600 dark:text-blue-300",
  text: "border-amber-500/30 bg-amber-500/10 text-amber-600 dark:text-amber-300",
  manual: "border-border bg-muted text-muted-foreground",
};

export function TargetPageCell({
  keyword,
  siteId,
  onChanged,
}: {
  keyword: Keyword;
  siteId: string;
  onChanged?: () => void;
}) {
  const t = useTranslations("Keywords");
  const target = keyword.targetPage ?? null;

  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const [results, setResults] = useState<SitePageOption[]>([]);
  const [searching, setSearching] = useState(false);
  const [pending, startTransition] = useTransition();

  const SOURCE_LABEL: Record<TargetSource, string> = {
    gsc: t("targetPageSourceGsc"),
    content: t("targetPageSourceContent"),
    text: t("targetPageSourceText"),
    manual: t("targetPageSourceManual"),
  };

  // Debounced search (300ms) — only while the picker is open. An empty query
  // still fetches (the action returns the most recent pages, limit 20).
  useEffect(() => {
    if (!open) return;
    let cancelled = false;
    setSearching(true);
    const handle = setTimeout(() => {
      searchSitePagesAction(siteId, query)
        .then((rows) => {
          if (!cancelled) setResults(rows);
        })
        .catch(() => {
          if (!cancelled) setResults([]);
        })
        .finally(() => {
          if (!cancelled) setSearching(false);
        });
    }, 300);
    return () => {
      cancelled = true;
      clearTimeout(handle);
    };
  }, [open, query, siteId]);

  function assign(pageId: string | null) {
    startTransition(async () => {
      const res = await setKeywordTargetPageAction(siteId, keyword.id, pageId);
      if (res.ok) {
        toast.success(
          pageId ? t("targetPageSetSuccess") : t("targetPageRemoveSuccess"),
        );
        setOpen(false);
        onChanged?.();
      } else {
        toast.error(t("targetPageError"));
      }
    });
  }

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger
        // Stop the click from bubbling to the row (which opens the keyword sheet).
        onClick={(e) => e.stopPropagation()}
        className={cn(
          "inline-flex max-w-[16rem] items-center gap-1.5 rounded-md border px-2 py-1 text-left text-[12.5px] transition-colors",
          target
            ? "border-transparent hover:bg-accent"
            : "border-blue-500/40 border-dashed bg-blue-500/5 text-blue-600 hover:bg-blue-500/10 dark:text-blue-300",
        )}
        aria-label={
          target ? t("targetPageEditAria") : t("targetPageAssignAria")
        }
      >
        {target ? (
          <TooltipProvider>
            <Tooltip>
              <TooltipTrigger asChild>
                <span className="flex min-w-0 items-center gap-1.5">
                  <span className="truncate font-medium">
                    {shortPath(target.url)}
                  </span>
                  <span
                    className={cn(
                      "inline-flex shrink-0 items-center rounded-full border px-1.5 py-px font-semibold text-[10px]",
                      SOURCE_BADGE[target.source],
                    )}
                  >
                    {SOURCE_LABEL[target.source]}
                  </span>
                </span>
              </TooltipTrigger>
              <TooltipContent className="max-w-sm break-all">
                <span className="block">{target.url}</span>
                {target.source === "text" && target.score != null ? (
                  <span className="mt-0.5 block text-muted-foreground">
                    {t("targetPageScore", { score: target.score })}
                  </span>
                ) : null}
              </TooltipContent>
            </Tooltip>
          </TooltipProvider>
        ) : (
          <span className="inline-flex items-center gap-1.5">
            <LinkIcon className="size-3.5" aria-hidden />
            {t("targetPageAssign")}
          </span>
        )}
      </PopoverTrigger>
      <PopoverContent
        align="start"
        className="w-80 gap-2 p-2"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="relative">
          <SearchIcon
            className="-translate-y-1/2 absolute top-1/2 left-2.5 size-3.5 text-muted-foreground"
            aria-hidden
          />
          <Input
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder={t("targetPageSearchPlaceholder")}
            aria-label={t("targetPageSearchPlaceholder")}
            className="h-9 pl-8"
          />
        </div>
        <div className="max-h-64 overflow-y-auto">
          {searching && results.length === 0 ? (
            <p className="px-1 py-4 text-center text-muted-foreground text-xs">
              {t("targetPageSearching")}
            </p>
          ) : results.length === 0 ? (
            <p className="px-1 py-4 text-center text-muted-foreground text-xs">
              {t("targetPageEmpty")}
            </p>
          ) : (
            <ul className="flex flex-col">
              {results.map((page) => {
                const selected = target?.url === page.url;
                return (
                  <li key={page.id}>
                    <button
                      type="button"
                      disabled={pending}
                      onClick={() => assign(page.id)}
                      className={cn(
                        "flex w-full flex-col items-start gap-0.5 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-accent disabled:opacity-60",
                        selected && "bg-accent",
                      )}
                    >
                      {page.title ? (
                        <span className="w-full truncate font-medium text-[13px]">
                          {page.title}
                        </span>
                      ) : null}
                      <span className="w-full truncate text-[11.5px] text-muted-foreground">
                        {page.url}
                      </span>
                    </button>
                  </li>
                );
              })}
            </ul>
          )}
        </div>
        {target ? (
          <button
            type="button"
            disabled={pending}
            onClick={() => assign(null)}
            className="inline-flex items-center gap-1.5 rounded-md px-2 py-1.5 text-left text-[12.5px] text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:opacity-60"
          >
            <XIcon className="size-3.5" aria-hidden />
            {t("targetPageRemove")}
          </button>
        ) : null}
      </PopoverContent>
    </Popover>
  );
}
