import { useState, useCallback, useRef, useEffect } from "react";
import { Send, FlaskConical, ShieldAlert, AlertCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Badge } from "@/components/ui/badge";
import { Skeleton } from "@/components/ui/skeleton";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { PiiHighlight } from "@/components/PiiHighlight";
import { usePiiAnalyze } from "@/api/pii";
import { apiFetch } from "@/api/client";
import type { PiiEntity } from "@/types/api";

const MODELS = [
  { value: "gpt-4o-mini", label: "GPT-4o Mini" },
  { value: "gpt-4o", label: "GPT-4o" },
  { value: "claude-3-5-haiku-20241022", label: "Claude 3.5 Haiku" },
  { value: "mistral-small-latest", label: "Mistral Small" },
  { value: "llama3.2", label: "Llama 3.2 (Ollama)" },
];

const DEBOUNCE_MS = 600;

// Legend mapping — covers both Python PII service types and Go regex-local fallback types.
const ENTITY_LEGEND: Record<string, string> = {
  IBAN_CODE: "bg-red-100 text-red-800", IBAN: "bg-red-100 text-red-800",
  CREDIT_CARD: "bg-red-100 text-red-800",
  EMAIL_ADDRESS: "bg-orange-100 text-orange-800", EMAIL: "bg-orange-100 text-orange-800",
  PHONE_NUMBER: "bg-purple-100 text-purple-800", PHONE_FR: "bg-purple-100 text-purple-800", PHONE_INTL: "bg-purple-100 text-purple-800",
  PERSON: "bg-blue-100 text-blue-800", PER: "bg-blue-100 text-blue-800",
  FR_SSN: "bg-rose-100 text-rose-800", FR_NIF: "bg-rose-100 text-rose-800",
  LOCATION: "bg-green-100 text-green-800", LOC: "bg-green-100 text-green-800", GPE: "bg-green-100 text-green-800",
  ORGANIZATION: "bg-teal-100 text-teal-800", ORG: "bg-teal-100 text-teal-800",
};

interface ChatMessage {
  role: "user" | "assistant";
  content: string;
}

export function PlaygroundPage() {
  const [text, setText] = useState("");
  const [model, setModel] = useState(MODELS[0].value);
  const [entities, setEntities] = useState<PiiEntity[]>([]);
  const [anonymized, setAnonymized] = useState("");
  const [piiLayer, setPiiLayer] = useState<"service" | "regex" | "none">("none");
  const [aiResponse, setAiResponse] = useState("");
  const [isSending, setIsSending] = useState(false);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // ── PII mutation ──────────────────────────────────────────────────────────
  // useMutation returns a new object every render; store it in a ref so that
  // handleTextChange (empty deps) always calls the latest version without
  // being recreated on every render (which would cancel the debounce).
  const piiMutation = usePiiAnalyze();
  const piiMutationRef = useRef(piiMutation);
  piiMutationRef.current = piiMutation;

  const handleTextChange = useCallback((value: string) => {
    setText(value);
    if (debounceRef.current) clearTimeout(debounceRef.current);
    if (!value.trim()) {
      setEntities([]);
      setAnonymized("");
      setPiiLayer("none");
      return;
    }
    debounceRef.current = setTimeout(() => {
      piiMutationRef.current.mutate(value, {
        onSuccess: (result) => {
          setEntities(result.entities);
          setAnonymized(result.anonymized);
          const layer = result.entities.some((e) => e.layer === "regex-local")
            ? "regex"
            : result.entities.length > 0
            ? "service"
            : "none";
          setPiiLayer(layer);
        },
        onError: () => {
          setEntities([]);
          setAnonymized(value);
          setPiiLayer("none");
        },
      });
    }, DEBOUNCE_MS);
  }, []); // stable — uses ref internally

  useEffect(() => {
    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
  }, []);

  // ── LLM send ─────────────────────────────────────────────────────────────
  const handleSend = async () => {
    if (!text.trim() || isSending) return;
    setIsSending(true);
    setAiResponse("");
    try {
      const messages: ChatMessage[] = [{ role: "user", content: text }];
      const response = await apiFetch<{ choices: { message: { content: string } }[] }>(
        "/v1/chat/completions",
        { method: "POST", body: JSON.stringify({ model, messages, stream: false }) }
      );
      setAiResponse(response.choices?.[0]?.message?.content ?? "");
    } catch (err) {
      setAiResponse(`Erreur : ${err instanceof Error ? err.message : "Requête échouée"}`);
    } finally {
      setIsSending(false);
    }
  };

  const piiCount = entities.length;
  const hasText = text.trim().length > 0;
  const uniqueTypes = [...new Set(entities.map((e) => e.type))];

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-xl font-bold flex items-center gap-2">
            <FlaskConical className="h-5 w-5 text-primary" />
            Playground IA
          </h2>
          <p className="text-sm text-muted-foreground">
            Testez vos prompts avec détection PII en temps réel
          </p>
        </div>
        <div className="flex items-center gap-3">
          <Select value={model} onValueChange={setModel}>
            <SelectTrigger className="w-48">
              <SelectValue placeholder="Modèle" />
            </SelectTrigger>
            <SelectContent>
              {MODELS.map((m) => (
                <SelectItem key={m.value} value={m.value}>
                  {m.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Button onClick={handleSend} disabled={!hasText || isSending}>
            <Send className="h-4 w-4 mr-2" />
            {isSending ? "Envoi…" : "Envoyer"}
          </Button>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        {/* Left: Input */}
        <div className="space-y-3">
          <div className="flex items-center justify-between min-h-[24px]">
            <label className="text-sm font-medium">Votre prompt</label>
            <div className="flex items-center gap-2">
              {piiMutation.isPending && (
                <span className="text-xs text-muted-foreground animate-pulse">
                  Analyse PII…
                </span>
              )}
              {piiCount > 0 && (
                <Badge
                  className="gap-1 bg-amber-100 text-amber-800 border-amber-200 hover:bg-amber-100"
                >
                  <ShieldAlert className="h-3 w-3" />
                  {piiCount} donnée{piiCount > 1 ? "s" : ""} sensible
                  {piiCount > 1 ? "s" : ""}
                </Badge>
              )}
            </div>
          </div>
          <Textarea
            value={text}
            onChange={(e) => handleTextChange(e.target.value)}
            placeholder="Tapez votre prompt ici… Ex : Mon IBAN est FR7630006000011234567890189 et je m'appelle Jean Dupont."
            className="min-h-[200px] font-mono text-sm resize-y"
          />
        </div>

        {/* Right: Results */}
        <div className="space-y-3">
          {/* PII highlight panel */}
          <div>
            <div className="flex items-center justify-between mb-1">
              <label className="text-sm font-medium">Analyse PII (temps réel)</label>
              {piiLayer === "regex" && (
                <span className="flex items-center gap-1 text-xs text-amber-600">
                  <AlertCircle className="h-3 w-3" />
                  Détection locale (service PII non disponible)
                </span>
              )}
              {piiLayer === "service" && (
                <span className="text-xs text-green-600">Service PII actif</span>
              )}
            </div>
            <div className="min-h-[200px] rounded-md border bg-muted/30 p-3 text-sm leading-relaxed whitespace-pre-wrap">
              {hasText ? (
                <PiiHighlight text={text} entities={entities} />
              ) : (
                <span className="text-muted-foreground italic">
                  Commencez à taper pour voir les données sensibles surlignées…
                </span>
              )}
            </div>
          </div>

          {/* Anonymized prompt */}
          {anonymized && anonymized !== text && (
            <div>
              <label className="text-sm font-medium text-muted-foreground">
                Prompt anonymisé (envoyé à l&apos;IA)
              </label>
              <div className="mt-1 min-h-[60px] rounded-md border bg-muted/50 p-3 text-xs font-mono leading-relaxed whitespace-pre-wrap text-muted-foreground">
                {anonymized}
              </div>
            </div>
          )}

          {/* AI response */}
          {(isSending || aiResponse) && (
            <div>
              <label className="text-sm font-medium">Réponse de l&apos;IA</label>
              <div className="mt-1 min-h-[80px] rounded-md border p-3 text-sm leading-relaxed whitespace-pre-wrap">
                {isSending ? (
                  <div className="space-y-2">
                    <Skeleton className="h-4 w-3/4" />
                    <Skeleton className="h-4 w-full" />
                    <Skeleton className="h-4 w-1/2" />
                  </div>
                ) : (
                  aiResponse
                )}
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Legend */}
      {piiCount > 0 && (
        <div className="flex flex-wrap gap-2 pt-2 border-t">
          <span className="text-xs text-muted-foreground">Légende :</span>
          {uniqueTypes.map((type) => (
            <span
              key={type}
              className={`text-xs px-2 py-0.5 rounded font-medium ${
                ENTITY_LEGEND[type] ?? "bg-yellow-100 text-yellow-800"
              }`}
            >
              {type}
            </span>
          ))}
        </div>
      )}
    </div>
  );
}
