"use client";

import { useRef, useState, useTransition } from "react";
import { createSiteAction, preflightAction } from "@/app/(app)/settings/sites/new/actions";
import { Spinner } from "@/components/app/spinner";
import { LocaleSelect } from "@/components/sites/locale-select";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  COUNTRIES,
  DEFAULT_COUNTRY,
  DEFAULT_LANGUAGE,
  knownCountry,
  knownLanguage,
  LANGUAGES,
} from "@/lib/locales";
import type { CheckResult, PreflightReport } from "@/lib/sites";
import { cn } from "@/lib/utils";

type TargetRow = { key: number; country: string; language: string; is_default: boolean };

const STATUS_LABELS: Record<CheckResult["status"], string> = {
  ok: "OK",
  warning: "Avertissement",
  failed: "Échec",
  skipped: "Ignoré",
};

const STATUS_VARIANTS: Record<CheckResult["status"], "secondary" | "outline" | "destructive"> = {
  ok: "secondary",
  warning: "outline",
  failed: "destructive",
  skipped: "outline",
};

const CHECK_LABELS = {
  dns: "DNS",
  home: "Page d'accueil",
  robots: "robots.txt",
  sitemap: "Sitemap",
} as const;

const STEPS = [
  { title: "Domaine", description: "Le domaine ou l'URL du site à suivre." },
  { title: "Cibles", description: "Les couples pays · langue analysés pour ce site." },
  { title: "Lancement", description: "Récapitulatif avant création." },
];

export function SiteWizard() {
  const [step, setStep] = useState<1 | 2 | 3>(1);
  const [domain, setDomain] = useState("");
  const [report, setReport] = useState<PreflightReport | null>(null);
  const [invalidDomain, setInvalidDomain] = useState(false);
  const [useFinalHost, setUseFinalHost] = useState(true);
  const [targets, setTargets] = useState<TargetRow[]>([
    { key: 0, country: DEFAULT_COUNTRY, language: DEFAULT_LANGUAGE, is_default: true },
  ]);
  const [error, setError] = useState<string | null>(null);
  const [pending, startTransition] = useTransition();
  // Clés stables et déterministes (pas de crypto.randomUUID : mismatch SSR/hydratation).
  const nextKey = useRef(1);

  const finalHost = report?.final_host ?? null;
  const effectiveDomain = finalHost && useFinalHost ? finalHost : domain.trim();

  const verify = () => {
    setError(null);
    startTransition(async () => {
      const result = await preflightAction({ domain });
      if ("error" in result) {
        setReport(null);
        // Seul un domaine syntaxiquement invalide (422) arrête l'écran 1 (spec §2).
        setInvalidDomain(result.status === 422);
        setError(result.error);
        return;
      }
      setInvalidDomain(false);
      setUseFinalHost(true); // bascule vers final_host pré-cochée (décision §10.4)
      setReport(result.report);
      setTargets([
        {
          key: nextKey.current++,
          country: knownCountry(result.report.suggested_target.country),
          language: knownLanguage(result.report.suggested_target.language),
          is_default: true,
        },
      ]);
    });
  };

  const updateTarget = (key: number, patch: Partial<TargetRow>) => {
    setTargets((rows) => rows.map((row) => (row.key === key ? { ...row, ...patch } : row)));
  };

  const create = () => {
    setError(null);
    startTransition(async () => {
      // Succès = redirect('/settings/sites/{id}') côté serveur : on ne revient ici qu'en erreur.
      const result = await createSiteAction({
        domain: effectiveDomain,
        targets: targets.map(({ country, language, is_default }) => ({
          country,
          language,
          is_default,
        })),
      });
      setError(result.error);
      // 409 (domaine déjà suivi) ou 422 : l'erreur se corrige à l'écran 1.
      if (result.status === 409 || result.status === 422) setStep(1);
    });
  };

  const current = STEPS[step - 1];

  return (
    <div className="space-y-4">
      <ol className="text-muted-foreground flex flex-wrap items-center gap-x-4 gap-y-1 text-sm">
        {STEPS.map((item, index) => (
          <li
            key={item.title}
            aria-current={step === index + 1 ? "step" : undefined}
            className={cn("flex items-center gap-2", step === index + 1 && "text-foreground")}
          >
            <span
              className={cn(
                "flex size-5 items-center justify-center rounded-full border text-xs",
                step === index + 1 && "bg-primary text-primary-foreground border-transparent",
                step > index + 1 && "border-foreground/40",
              )}
            >
              {index + 1}
            </span>
            {item.title}
          </li>
        ))}
      </ol>

      <Card>
        <CardHeader>
          <CardTitle>{current.title}</CardTitle>
          <CardDescription>{current.description}</CardDescription>
        </CardHeader>

        <CardContent className="space-y-4">
          {step === 1 ? (
            <>
              <div className="max-w-md space-y-1">
                <Label htmlFor="wizard-domain">Domaine ou URL du site</Label>
                <Input
                  id="wizard-domain"
                  placeholder="https://exemple.fr"
                  value={domain}
                  aria-invalid={invalidDomain}
                  onChange={(event) => {
                    setDomain(event.target.value);
                    setInvalidDomain(false);
                    setReport(null);
                  }}
                />
              </div>
              {report ? (
                <div className="max-w-md space-y-3 rounded-lg border p-4 text-sm">
                  <ul className="space-y-2">
                    {(Object.keys(CHECK_LABELS) as (keyof typeof CHECK_LABELS)[]).map((key) => {
                      const check = report.checks[key];
                      return (
                        <li key={key} className="flex items-start justify-between gap-4">
                          <span>{CHECK_LABELS[key]}</span>
                          <span className="flex flex-col items-end gap-1 text-right">
                            <Badge variant={STATUS_VARIANTS[check.status]}>
                              {STATUS_LABELS[check.status]}
                            </Badge>
                            {check.detail ? (
                              <span className="text-muted-foreground text-xs">{check.detail}</span>
                            ) : null}
                          </span>
                        </li>
                      );
                    })}
                  </ul>
                  {finalHost ? (
                    <div className="flex items-start gap-2">
                      <Checkbox
                        id="wizard-final-host"
                        checked={useFinalHost}
                        onCheckedChange={(checked) => setUseFinalHost(checked === true)}
                      />
                      <Label htmlFor="wizard-final-host" className="items-start font-normal">
                        {report.domain} redirige vers {finalHost} : utiliser {finalHost}
                      </Label>
                    </div>
                  ) : null}
                </div>
              ) : null}
            </>
          ) : null}

          {step === 2 ? (
            <>
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Pays</TableHead>
                    <TableHead>Langue</TableHead>
                    <TableHead>Par défaut</TableHead>
                    <TableHead />
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {targets.map((target, index) => (
                    <TableRow key={target.key}>
                      <TableCell className="w-[38%]">
                        <LocaleSelect
                          id={`target-country-${target.key}`}
                          label={`Pays de la cible ${index + 1}`}
                          options={COUNTRIES}
                          value={target.country}
                          onValueChange={(value) => updateTarget(target.key, { country: value })}
                        />
                      </TableCell>
                      <TableCell className="w-[38%]">
                        <LocaleSelect
                          id={`target-language-${target.key}`}
                          label={`Langue de la cible ${index + 1}`}
                          options={LANGUAGES}
                          value={target.language}
                          onValueChange={(value) => updateTarget(target.key, { language: value })}
                        />
                      </TableCell>
                      <TableCell>
                        <input
                          type="radio"
                          name="default-target"
                          aria-label={`Cible par défaut ${index + 1}`}
                          checked={target.is_default}
                          onChange={() =>
                            setTargets((rows) =>
                              rows.map((row) => ({ ...row, is_default: row.key === target.key })),
                            )
                          }
                        />
                      </TableCell>
                      <TableCell className="text-right">
                        <Button
                          type="button"
                          variant="ghost"
                          size="sm"
                          disabled={target.is_default || targets.length === 1}
                          onClick={() =>
                            setTargets((rows) => rows.filter((row) => row.key !== target.key))
                          }
                        >
                          Retirer
                        </Button>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
              <Button
                type="button"
                variant="outline"
                disabled={targets.length >= 20}
                onClick={() =>
                  setTargets((rows) => [
                    ...rows,
                    {
                      key: nextKey.current++,
                      country: DEFAULT_COUNTRY,
                      language: DEFAULT_LANGUAGE,
                      is_default: false,
                    },
                  ])
                }
              >
                Ajouter une cible
              </Button>
            </>
          ) : null}

          {step === 3 ? (
            <dl className="max-w-md space-y-2 rounded-lg border p-4 text-sm">
              <div className="flex gap-2">
                <dt className="text-muted-foreground">Domaine :</dt>
                <dd>{effectiveDomain}</dd>
              </div>
              <div className="flex gap-2">
                <dt className="text-muted-foreground">Cibles :</dt>
                <dd>
                  {targets
                    .map((t) => `${t.country} · ${t.language}${t.is_default ? " (défaut)" : ""}`)
                    .join(", ")}
                </dd>
              </div>
              <p className="text-muted-foreground">
                Le crawl démarrera ici automatiquement (module Crawl à venir).
              </p>
            </dl>
          ) : null}

          {error ? (
            <p role="alert" className="text-destructive text-sm">
              {error}
            </p>
          ) : null}
        </CardContent>

        <CardFooter className="gap-2">
          {step === 1 ? (
            <>
              <Button
                type="button"
                variant="outline"
                disabled={pending || domain.trim().length === 0}
                onClick={verify}
              >
                {/* Le preflight fait quatre appels réseau (DNS, home, robots, sitemap) :
                    plusieurs secondes pendant lesquelles le bouton doit avouer qu'il travaille. */}
                {pending ? <Spinner size="sm" data-icon="inline-start" /> : null}
                Vérifier
              </Button>
              <Button
                type="button"
                disabled={pending || domain.trim().length === 0 || invalidDomain}
                onClick={() => setStep(2)}
              >
                Continuer
              </Button>
            </>
          ) : null}
          {step === 2 ? (
            <>
              <Button type="button" variant="outline" onClick={() => setStep(1)}>
                Retour
              </Button>
              <Button type="button" onClick={() => setStep(3)}>
                Continuer
              </Button>
            </>
          ) : null}
          {step === 3 ? (
            <>
              <Button type="button" variant="outline" disabled={pending} onClick={() => setStep(2)}>
                Retour
              </Button>
              <Button type="button" disabled={pending} onClick={create}>
                Créer le site
              </Button>
            </>
          ) : null}
        </CardFooter>
      </Card>
    </div>
  );
}
