import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import { Check, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Slider } from "@/components/ui/slider";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import { useIeltsContentPool, useIeltsAutoAssemble, useIeltsSkills } from "@/hooks/queries/useExamTemplates";
import { ieltsExamService } from "@/services/ielts-exam.service";
import type { ContentPoolFilters, ContentPoolItem, ExamDifficulty, IELTSSkill, IELTSSkillConfig } from "@/types";
import { toast } from "sonner";

const SKILLS: { value: IELTSSkill; label: string }[] = [
  { value: "listening", label: "Listening" },
  { value: "reading", label: "Reading" },
  { value: "writing", label: "Writing" },
  { value: "speaking", label: "Speaking" },
];

function difficultyLabel(d: ExamDifficulty): string {
  return d.charAt(0).toUpperCase() + d.slice(1);
}

export default function IeltsContentPool() {
  const { examId: examIdParam } = useParams<{ examId: string }>();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const examId = Number(examIdParam);

  const [skill, setSkill] = useState<IELTSSkill>(() => (searchParams.get("skill") as IELTSSkill) || "listening");
  const [part, setPart] = useState<number>(() => Number(searchParams.get("part")) || 1);
  const [difficultyIdx, setDifficultyIdx] = useState(1);
  const difficulties: ExamDifficulty[] = ["easy", "medium", "hard"];
  const difficulty = difficulties[difficultyIdx] ?? "medium";
  const [topicInput, setTopicInput] = useState("");
  const [search, setSearch] = useState("");
  const [selected, setSelected] = useState<number[]>([]);
  const [pendingHybrid, setPendingHybrid] = useState<ContentPoolItem[]>([]);

  const assemblyMode = useMemo(() => {
    if (!Number.isFinite(examId)) return "manual";
    return sessionStorage.getItem(`ielts_assembly_${examId}`) ?? "manual";
  }, [examId]);

  const filters: ContentPoolFilters = useMemo(
    () => ({
      skill,
      part,
      difficulty,
      topics: topicInput
        .split(",")
        .map((t) => t.trim())
        .filter(Boolean),
      search: search.trim() || undefined,
    }),
    [skill, part, difficulty, topicInput, search],
  );

  const poolQ = useIeltsContentPool(Number.isFinite(examId) ? examId : 0, filters);
  const skillsQ = useIeltsSkills(Number.isFinite(examId) ? examId : 0);
  const autoAssemble = useIeltsAutoAssemble();

  const items = useMemo(() => {
    const raw = poolQ.data;
    if (Array.isArray(raw)) return raw;
    if (raw && typeof raw === "object" && Array.isArray((raw as { data?: unknown }).data)) {
      return (raw as { data: ContentPoolItem[] }).data;
    }
    return [] as ContentPoolItem[];
  }, [poolQ.data]);

  const skillsData = useMemo(() => {
    const raw = skillsQ.data;
    if (Array.isArray(raw)) return raw;
    if (raw && typeof raw === "object" && Array.isArray((raw as { data?: unknown }).data)) {
      return (raw as { data: IELTSSkillConfig[] }).data;
    }
    return [];
  }, [skillsQ.data]);

  const requiredTotal = useMemo(() => {
    const cfg = skillsData.find((s) => s.skill === skill);
    if (!cfg?.parts?.length) {
      if (skill === "listening") return 40;
      if (skill === "reading") return 40;
      if (skill === "writing") return 2;
      return 3;
    }
    return cfg.parts.reduce((a, p) => a + p.question_count, 0);
  }, [skillsData, skill]);

  useEffect(() => {
    setSearchParams(
      (prev) => {
        const sp = new URLSearchParams(prev);
        sp.set("skill", skill);
        sp.set("part", String(part));
        return sp;
      },
      { replace: true },
    );
  }, [skill, part, setSearchParams]);

  const didAutoRun = useRef(false);
  useEffect(() => {
    if (assemblyMode !== "auto" || !Number.isFinite(examId) || didAutoRun.current) return;
    didAutoRun.current = true;
    let cancelled = false;
    (async () => {
      try {
        const res = await autoAssemble.mutateAsync(examId);
        if (cancelled) return;
        const flat = (Array.isArray(res) ? res : []).flatMap((r) => r.selected_items?.map((i) => i.id) ?? []);
        setSelected(flat);
      } catch {
        toast.error("Auto-assembly could not run.");
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [assemblyMode, autoAssemble, examId]);

  useEffect(() => {
    if (assemblyMode !== "hybrid" || !Number.isFinite(examId)) return;
    let cancelled = false;
    (async () => {
      try {
        const res = await ieltsExamService.suggest(examId);
        if (cancelled) return;
        const rows = Array.isArray(res) ? res : [];
        const forSkill = rows.find((r) => r.skill === skill && r.part === part);
        setPendingHybrid(forSkill?.selected_items ?? []);
      } catch {
        setPendingHybrid([]);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [assemblyMode, examId, part, skill]);

  const toggleSelect = useCallback(
    (id: number) => {
      setSelected((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]));
    },
    [],
  );

  const selectedItems = useMemo(() => {
    const map = new Map(items.map((i) => [i.id, i]));
    return selected.map((id) => map.get(id)).filter(Boolean) as ContentPoolItem[];
  }, [items, selected]);

  const poolDisabled = assemblyMode === "auto";

  const saveContinue = async () => {
    try {
      await ieltsExamService.saveQuestions(examId, part, selected);
      toast.success("Selections saved.");
      navigate(`/admin/exam/ielts/${examId}/validate`);
    } catch {
      toast.error("Save failed.");
    }
  };

  if (!Number.isFinite(examId) || examId <= 0) {
    return <p className="p-6 text-destructive">Invalid exam.</p>;
  }

  return (
    <div className="p-6 max-w-[1400px] mx-auto space-y-6">
      <div>
        <h1 className="text-2xl font-semibold tracking-tight">Content pool</h1>
        <p className="text-muted-foreground mt-1">
          Assembly: <span className="text-foreground font-medium capitalize">{assemblyMode}</span>
          {assemblyMode === "auto" ? " — pool is read-only; system selections apply." : null}
          {assemblyMode === "hybrid" ? " — review suggestions on the right." : null}
        </p>
      </div>

      <div className="grid gap-4 lg:grid-cols-5">
        <Card className="lg:col-span-3">
          <CardHeader>
            <CardTitle>Browse pool</CardTitle>
            <CardDescription>Filter and preview candidate items.</CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="grid gap-3 sm:grid-cols-2">
              <div className="space-y-2">
                <Label>Skill</Label>
                <Select value={skill} onValueChange={(v) => setSkill(v as IELTSSkill)}>
                  <SelectTrigger>
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {SKILLS.map((s) => (
                      <SelectItem key={s.value} value={s.value}>
                        {s.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-2">
                <Label>Part</Label>
                <Select value={String(part)} onValueChange={(v) => setPart(Number(v))}>
                  <SelectTrigger>
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {[1, 2, 3, 4].map((n) => (
                      <SelectItem key={n} value={String(n)}>
                        Part {n}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            </div>
            <div className="space-y-2">
              <Label>Difficulty ({difficultyLabel(difficulty)})</Label>
              <Slider min={0} max={2} step={1} value={[difficultyIdx]} onValueChange={(v) => setDifficultyIdx(v[0] ?? 1)} />
            </div>
            <div className="space-y-2">
              <Label htmlFor="topics">Topic tags</Label>
              <Input
                id="topics"
                placeholder="education, environment …"
                value={topicInput}
                onChange={(e) => setTopicInput(e.target.value)}
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="search">Search</Label>
              <Input id="search" placeholder="Keyword in stem" value={search} onChange={(e) => setSearch(e.target.value)} />
            </div>

            <Separator />

            {poolQ.isLoading ? (
              <div className="space-y-2">
                <Skeleton className="h-24 w-full" />
                <Skeleton className="h-24 w-full" />
              </div>
            ) : (
              <ScrollArea className="h-[min(520px,55vh)] pr-3">
                <div className={`space-y-3 ${poolDisabled ? "opacity-50 pointer-events-none" : ""}`}>
                  {items.map((item) => (
                    <Card key={item.id} className="border-muted">
                      <CardHeader className="py-3 space-y-1">
                        <div className="flex flex-wrap items-center gap-2">
                          <Badge variant="outline">{difficultyLabel(item.difficulty)}</Badge>
                          <span className="text-xs text-muted-foreground">Used {item.usage_count}×</span>
                        </div>
                        <CardTitle className="text-sm font-normal leading-snug">{item.preview_text}</CardTitle>
                        <div className="flex flex-wrap gap-1">
                          {item.topic_tags.map((t) => (
                            <Badge key={t} variant="secondary" className="text-xs">
                              {t}
                            </Badge>
                          ))}
                        </div>
                      </CardHeader>
                      <CardContent className="pt-0 flex justify-end gap-2">
                        <Button
                          type="button"
                          size="sm"
                          variant={selected.includes(item.id) ? "secondary" : "default"}
                          disabled={poolDisabled}
                          onClick={() => toggleSelect(item.id)}
                        >
                          {selected.includes(item.id) ? "Remove" : "Add"}
                        </Button>
                      </CardContent>
                    </Card>
                  ))}
                  {items.length === 0 ? <p className="text-sm text-muted-foreground">No items match these filters.</p> : null}
                </div>
              </ScrollArea>
            )}
          </CardContent>
        </Card>

        <Card className="lg:col-span-2">
          <CardHeader>
            <CardTitle>Selected questions</CardTitle>
            <CardDescription>
              {selected.length}/{requiredTotal} selected
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <ScrollArea className="h-[min(400px,45vh)]">
              <ul className="space-y-2 text-sm">
                {selectedItems.map((i) => (
                  <li key={i.id} className="rounded-md border p-2 flex justify-between gap-2">
                    <span className="line-clamp-2">{i.preview_text}</span>
                    <Button type="button" size="icon" variant="ghost" className="shrink-0" onClick={() => toggleSelect(i.id)}>
                      <X className="h-4 w-4" />
                    </Button>
                  </li>
                ))}
                {selectedItems.length === 0 ? <li className="text-muted-foreground">Nothing selected yet.</li> : null}
              </ul>
            </ScrollArea>

            {assemblyMode === "hybrid" && pendingHybrid.length > 0 ? (
              <div className="space-y-2">
                <p className="text-sm font-medium">Suggestions</p>
                {pendingHybrid.map((item) => (
                  <div key={item.id} className="flex items-start justify-between gap-2 rounded-md border p-2 text-sm">
                    <span className="line-clamp-3">{item.preview_text}</span>
                    <div className="flex gap-1 shrink-0">
                      <Button
                        type="button"
                        size="icon"
                        variant="outline"
                        onClick={() => {
                          if (!selected.includes(item.id)) setSelected((s) => [...s, item.id]);
                          setPendingHybrid((p) => p.filter((x) => x.id !== item.id));
                        }}
                      >
                        <Check className="h-4 w-4" />
                      </Button>
                      <Button
                        type="button"
                        size="icon"
                        variant="ghost"
                        onClick={() => setPendingHybrid((p) => p.filter((x) => x.id !== item.id))}
                      >
                        <X className="h-4 w-4" />
                      </Button>
                    </div>
                  </div>
                ))}
              </div>
            ) : null}

            <Button className="w-full" type="button" onClick={saveContinue}>
              Save & continue
            </Button>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}
