import { useEffect, useMemo, useRef, useState } from "react";
import { useParams, useNavigate, useOutletContext } from "react-router-dom";
import { supabase } from "@/integrations/supabase/client";
import { useWorkspace, DocumentRow, FlashcardRow, NoteRow, PodcastRow, QuizQuestionRow, QuizRow } from "@/store/workspace";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { useToast } from "@/hooks/use-toast";
import MarkdownView from "@/components/MarkdownView";
import { FileText, Layers, ListChecks, Headphones, MessagesSquare, Loader2, Trash2, ChevronLeft, Sparkles, RefreshCw, Menu } from "lucide-react";
import { useAuth } from "@/hooks/useAuth";
import { streamNotes, generateDerivatives } from "@/lib/pipeline";
import { generatePodcast } from "@/lib/podcast";
import FlashcardsDeck from "@/components/FlashcardsDeck";
import QuizPlayer from "@/components/QuizPlayer";
import ChatPanel from "@/components/ChatPanel";

export default function DocumentWorkspace() {
  const { docId } = useParams();
  const navigate = useNavigate();
  const { user } = useAuth();
  const { toast } = useToast();
  const outlet = useOutletContext<{ openMobileNav?: () => void }>();
  const {
    documents, upsertDocument, removeDocument,
    notes, flashcards, quiz, podcast,
    setNote, setFlashcards, setQuiz, setPodcast,
  } = useWorkspace();

  const doc = useMemo<DocumentRow | undefined>(
    () => documents.find((d) => d.id === docId),
    [documents, docId]
  );
  const [loading, setLoading] = useState(true);
  const [streaming, setStreaming] = useState(false);
  const autoStartedRef = useRef<string | null>(null);

  useEffect(() => {
    if (!docId || !user) return;
    let mounted = true;
    setLoading(true);

    (async () => {
      const { data: docRow } = await supabase
        .from("documents")
        .select("id,title,source_type,status,error_code,created_at")
        .eq("id", docId)
        .maybeSingle();
      if (docRow && mounted) upsertDocument(docRow as DocumentRow);

      const [n, f, q, p] = await Promise.all([
        supabase.from("notes").select("id,document_id,markdown").eq("document_id", docId).maybeSingle(),
        supabase.from("flashcards").select("id,document_id,front,back,order_index").eq("document_id", docId).order("order_index"),
        supabase.from("quizzes").select("id,document_id,title").eq("document_id", docId).maybeSingle(),
        supabase.from("podcasts").select("id,document_id,script,audio_url,status").eq("document_id", docId).maybeSingle(),
      ]);

      if (!mounted) return;
      setNote(docId, (n.data as NoteRow) ?? null);
      setFlashcards(docId, (f.data as FlashcardRow[]) ?? []);
      if (q.data) {
        const qq = await supabase
          .from("quiz_questions")
          .select("id,quiz_id,question,type,choices,correct,explanation,order_index")
          .eq("quiz_id", q.data.id)
          .order("order_index");
        setQuiz(docId, { ...(q.data as any), questions: (qq.data ?? []) as QuizQuestionRow[] } as QuizRow);
      } else {
        setQuiz(docId, null);
      }
      setPodcast(docId, (p.data as PodcastRow) ?? null);
      setLoading(false);
    })();

    // Realtime: document status updates
    const channel = supabase
      .channel(`doc-${docId}`)
      .on(
        "postgres_changes",
        { event: "UPDATE", schema: "public", table: "documents", filter: `id=eq.${docId}` },
        (payload) => upsertDocument(payload.new as DocumentRow),
      )
      .on(
        "postgres_changes",
        { event: "*", schema: "public", table: "podcasts", filter: `document_id=eq.${docId}` },
        (payload) => setPodcast(docId, (payload.new as PodcastRow) ?? null),
      )
      .subscribe();

    return () => {
      mounted = false;
      supabase.removeChannel(channel);
    };
  }, [docId, user, upsertDocument, setNote, setFlashcards, setQuiz, setPodcast]);

  const noteForDoc = docId ? notes[docId] ?? null : null;
  const docStatus = docId ? documents.find((d) => d.id === docId)?.status : undefined;

  const generate = async () => {
    if (!docId || streaming) return;
    setStreaming(true);
    setNote(docId, { id: "draft", document_id: docId, markdown: "" } as NoteRow);
    try {
      const final = await streamNotes({
        documentId: docId,
        onDelta: (chunk) => {
          const cur = (useWorkspace.getState().notes[docId]?.markdown ?? "") + chunk;
          setNote(docId, { id: "draft", document_id: docId, markdown: cur } as NoteRow);
        },
      });
      const { data: fresh } = await supabase
        .from("notes")
        .select("id,document_id,markdown")
        .eq("document_id", docId)
        .maybeSingle();
      setNote(docId, (fresh as NoteRow) ?? { id: "draft", document_id: docId, markdown: final });
    } catch (e: any) {
      toast({ title: "Notes generation failed", description: e.message, variant: "destructive" });
    } finally {
      setStreaming(false);
    }
  };

  useEffect(() => {
    if (!docId) return;
    if (docStatus === "ready" && !noteForDoc?.markdown && autoStartedRef.current !== docId && !streaming) {
      autoStartedRef.current = docId;
      generate();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [docId, docStatus, noteForDoc?.markdown]);

  const [derivLoading, setDerivLoading] = useState(false);
  const [podcastLoading, setPodcastLoading] = useState(false);
  const runDerivatives = async () => {
    if (!docId || derivLoading) return;
    setDerivLoading(true);
    try {
      await generateDerivatives(docId);
      const [{ data: f }, { data: qq }] = await Promise.all([
        supabase.from("flashcards").select("id,document_id,front,back,order_index").eq("document_id", docId).order("order_index"),
        supabase.from("quizzes").select("id,document_id,title").eq("document_id", docId).maybeSingle(),
      ]);
      setFlashcards(docId, (f as FlashcardRow[]) ?? []);
      if (qq) {
        const { data: questions } = await supabase
          .from("quiz_questions")
          .select("id,quiz_id,question,type,choices,correct,explanation,order_index")
          .eq("quiz_id", qq.id)
          .order("order_index");
        setQuiz(docId, { ...(qq as any), questions: (questions ?? []) as QuizQuestionRow[] } as QuizRow);
      } else {
        setQuiz(docId, null);
      }
      toast({ title: "Flashcards & quiz ready" });
    } catch (e: any) {
      toast({ title: "Generation failed", description: e.message, variant: "destructive" });
    } finally {
      setDerivLoading(false);
    }
  };

  const refreshPodcast = async () => {
    if (!docId) return;
    const { data } = await supabase
      .from("podcasts")
      .select("id,document_id,script,audio_url,status")
      .eq("document_id", docId)
      .maybeSingle();
    setPodcast(docId, (data as PodcastRow) ?? null);
  };

  const runPodcast = async () => {
    if (!docId || podcastLoading) return;
    setPodcastLoading(true);
    setPodcast(docId, {
      id: pod?.id ?? "draft",
      document_id: docId,
      script: pod?.script ?? null,
      audio_url: null,
      status: "generating",
    });
    try {
      await generatePodcast(docId);
      await refreshPodcast();
      toast({ title: "Podcast ready", description: "Your audio recap is ready to play." });
    } catch (e: any) {
      await refreshPodcast();
      toast({ title: "Podcast generation failed", description: e.message, variant: "destructive" });
    } finally {
      setPodcastLoading(false);
    }
  };

  const handleDelete = async () => {
    if (!docId) return;
    if (!confirm("Delete this document and all its assets?")) return;
    const { error } = await supabase.from("documents").delete().eq("id", docId);
    if (error) {
      toast({ title: "Delete failed", description: error.message, variant: "destructive" });
      return;
    }
    removeDocument(docId);
    navigate("/app");
  };

  if (!doc) {
    return (
      <div className="h-full flex items-center justify-center">
        {loading ? <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" /> : (
          <div className="text-center">
            <p className="text-muted-foreground mb-4">Document not found.</p>
            <Button variant="outline" onClick={() => navigate("/app")}>
              <ChevronLeft className="h-4 w-4 mr-1" /> Back
            </Button>
          </div>
        )}
      </div>
    );
  }

  const note = notes[doc.id] ?? null;
  const cards = flashcards[doc.id] ?? [];
  const qz = quiz[doc.id] ?? null;
  const pod = podcast[doc.id] ?? null;
  const isProcessing = doc.status === "pending" || doc.status === "processing";

  return (
    <div className="h-full flex flex-col">
      {/* Header */}
      <div className="border-b border-border px-4 sm:px-6 py-3 sm:py-4 flex items-start justify-between gap-3">
        <div className="flex items-start gap-2 min-w-0 flex-1">
          {outlet?.openMobileNav && (
            <Button
              variant="ghost"
              size="icon"
              className="md:hidden -ml-2 mt-0.5 shrink-0"
              onClick={outlet.openMobileNav}
              aria-label="Open navigation"
            >
              <Menu className="h-5 w-5" />
            </Button>
          )}
          <div className="min-w-0">
            <div className="flex items-center gap-2 mb-1 flex-wrap">
              <Badge variant="outline" className="text-[10px] uppercase tracking-wide">{doc.source_type}</Badge>
              {doc.status === "ready" && <Badge variant="secondary" className="text-[10px]">Ready</Badge>}
              {isProcessing && <Badge className="text-[10px] bg-primary/20 text-primary border-primary/30">Processing…</Badge>}
              {doc.status === "failed" && <Badge variant="destructive" className="text-[10px]">{doc.error_code ?? "Failed"}</Badge>}
            </div>
            <h1 className="text-lg sm:text-xl font-semibold tracking-tight truncate">{doc.title}</h1>
          </div>
        </div>
        <Button variant="ghost" size="icon" onClick={handleDelete} title="Delete" className="shrink-0">
          <Trash2 className="h-4 w-4" />
        </Button>
      </div>

      {/* Main Content Area */}
      {isProcessing ? (
        <div className="flex-1 flex items-center justify-center p-6 bg-slate-950/50 relative overflow-hidden">
          {/* Background scanline effect */}
          <div className="absolute inset-0 pointer-events-none">
            <div className="w-full h-1 bg-primary/10 absolute top-0 animate-scanline opacity-20" />
            <div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_50%,rgba(14,165,233,0.05),transparent_70%)]" />
          </div>
          
          <ExpertProcessing status={doc.status} sourceType={doc.source_type} />
        </div>
      ) : (
        <Tabs defaultValue="notes" className="flex-1 flex flex-col overflow-hidden">
        <div className="border-b border-border px-2 sm:px-6 overflow-x-auto">
          <TabsList className="bg-transparent h-11 p-0 gap-1">
            <TabsTrigger value="notes" className="data-[state=active]:bg-muted"><FileText className="h-3.5 w-3.5 mr-1.5" /> Notes</TabsTrigger>
            <TabsTrigger value="flashcards" className="data-[state=active]:bg-muted"><Layers className="h-3.5 w-3.5 mr-1.5" /> Flashcards</TabsTrigger>
            <TabsTrigger value="quiz" className="data-[state=active]:bg-muted"><ListChecks className="h-3.5 w-3.5 mr-1.5" /> Quiz</TabsTrigger>
            <TabsTrigger value="podcast" className="data-[state=active]:bg-muted"><Headphones className="h-3.5 w-3.5 mr-1.5" /> Podcast</TabsTrigger>
            <TabsTrigger value="chat" className="data-[state=active]:bg-muted"><MessagesSquare className="h-3.5 w-3.5 mr-1.5" /> Chat</TabsTrigger>
          </TabsList>
        </div>

        <div className="flex-1 overflow-y-auto">
          <TabsContent value="notes" className="m-0 p-4 sm:p-6 w-full animate-fade-in">
            {note?.markdown ? (
              <div className="space-y-4">
                <MarkdownView>{note.markdown}</MarkdownView>
                {streaming && (
                  <div className="flex items-center gap-2 text-xs text-muted-foreground">
                    <Loader2 className="h-3.5 w-3.5 animate-spin" /> Generating…
                  </div>
                )}
              </div>
            ) : doc.status === "ready" ? (
              <div className="border border-dashed border-border rounded-xl p-10 text-center space-y-3">
                <h3 className="font-medium">Ready to generate</h3>
                <p className="text-sm text-muted-foreground">
                  Click below to stream AI-generated study notes.
                </p>
                <Button onClick={generate} disabled={streaming}>
                  {streaming ? <Loader2 className="h-4 w-4 mr-2 animate-spin" /> : <Sparkles className="h-4 w-4 mr-2" />}
                  Generate notes
                </Button>
              </div>
            ) : isProcessing ? (
              <Placeholder title="Extracting content…" desc="We're parsing your source. Notes will appear here automatically." />
            ) : doc.status === "failed" ? (
              <Placeholder title="Ingestion failed" desc={doc.error_code ?? "Something went wrong while parsing the source."} />
            ) : (
              <Placeholder title="No notes yet" desc="Waiting for the source to be processed." />
            )}
          </TabsContent>

          <TabsContent value="flashcards" className="m-0 p-4 sm:p-6 max-w-3xl mx-auto animate-fade-in">
            {cards.length === 0 ? (
              <DerivativesEmpty
                kind="flashcards"
                noteReady={!!note?.markdown}
                loading={derivLoading}
                onGenerate={runDerivatives}
              />
            ) : (
              <div className="space-y-4">
                <div className="flex items-center justify-between">
                  <h2 className="text-sm font-medium text-muted-foreground">{cards.length} flashcards</h2>
                  <Button variant="ghost" size="sm" onClick={runDerivatives} disabled={derivLoading}>
                    {derivLoading ? <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin" /> : <RefreshCw className="h-3.5 w-3.5 mr-1.5" />}
                    Regenerate
                  </Button>
                </div>
                <FlashcardsDeck cards={cards} />
              </div>
            )}
          </TabsContent>

          <TabsContent value="quiz" className="m-0 p-4 sm:p-6 max-w-3xl mx-auto animate-fade-in">
            {!qz || qz.questions.length === 0 ? (
              <DerivativesEmpty
                kind="quiz"
                noteReady={!!note?.markdown}
                loading={derivLoading}
                onGenerate={runDerivatives}
              />
            ) : (
              <div className="space-y-4">
                <div className="flex items-center justify-between">
                  <h2 className="text-sm font-medium text-muted-foreground">{qz.title} — {qz.questions.length} questions</h2>
                  <Button variant="ghost" size="sm" onClick={runDerivatives} disabled={derivLoading}>
                    {derivLoading ? <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin" /> : <RefreshCw className="h-3.5 w-3.5 mr-1.5" />}
                    Regenerate
                  </Button>
                </div>
                <QuizPlayer quiz={qz} />
              </div>
            )}
          </TabsContent>

          <TabsContent value="podcast" className="m-0 p-4 sm:p-6 max-w-3xl mx-auto animate-fade-in">
            {!note?.markdown ? (
              <Placeholder title="No podcast yet" desc="Generate notes first, then create a two-host audio recap here." />
            ) : pod?.audio_url ? (
              <div className="space-y-4">
                <div className="flex items-center justify-between gap-3">
                  <div>
                    <h2 className="text-sm font-medium">Audio summary ready</h2>
                    <p className="text-sm text-muted-foreground">Listen now or regenerate it from your latest notes.</p>
                  </div>
                  <Button variant="ghost" size="sm" onClick={runPodcast} disabled={podcastLoading}>
                    {podcastLoading ? <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin" /> : <RefreshCw className="h-3.5 w-3.5 mr-1.5" />}
                    Regenerate
                  </Button>
                </div>
                <audio controls src={pod.audio_url} className="w-full" />
                {pod.script ? (
                  <div className="border border-border rounded-xl p-4 space-y-2">
                    <h3 className="text-sm font-medium">Script</h3>
                    <pre className="whitespace-pre-wrap font-sans text-sm text-muted-foreground">{pod.script}</pre>
                  </div>
                ) : null}
              </div>
            ) : pod?.status === "generating" || podcastLoading ? (
              <div className="border border-dashed border-border rounded-xl p-10 text-center space-y-3">
                <div className="flex items-center justify-center gap-2 text-sm text-muted-foreground">
                  <Loader2 className="h-4 w-4 animate-spin" /> Generating podcast audio…
                </div>
                <p className="text-sm text-muted-foreground">This can take a minute depending on the script length.</p>
              </div>
            ) : pod?.status === "failed" ? (
              <div className="border border-dashed border-border rounded-xl p-10 text-center space-y-3">
                <h3 className="font-medium">Podcast generation failed</h3>
                <p className="text-sm text-muted-foreground">Try again to rebuild the two-host audio version.</p>
                <Button onClick={runPodcast} disabled={podcastLoading}>
                  {podcastLoading ? <Loader2 className="h-4 w-4 mr-2 animate-spin" /> : <Headphones className="h-4 w-4 mr-2" />}
                  Retry podcast
                </Button>
              </div>
            ) : (
              <div className="border border-dashed border-border rounded-xl p-10 text-center space-y-3">
                <h3 className="font-medium">Generate podcast</h3>
                <p className="text-sm text-muted-foreground">Create a two-host audio recap from your generated notes.</p>
                <Button onClick={runPodcast} disabled={podcastLoading}>
                  {podcastLoading ? <Loader2 className="h-4 w-4 mr-2 animate-spin" /> : <Headphones className="h-4 w-4 mr-2" />}
                  Generate podcast
                </Button>
              </div>
            )}
          </TabsContent>

          <TabsContent value="chat" className="m-0 p-4 sm:p-6 max-w-3xl mx-auto animate-fade-in">
            <ChatPanel documentId={doc.id} noteReady={!!note?.markdown} />
          </TabsContent>
        </div>
      </Tabs>
      )}
    </div>
  );
}

function ExpertProcessing({ status, sourceType }: { status: string; sourceType: string }) {
  const [step, setStep] = useState(0);
  const steps = [
    "Initializing Expert Extraction Engine...",
    "Analyzing Document Hierarchy...",
    "Mapping Frameworks & Key Concepts...",
    "Ensuring Lossless Capture of Sequential Data...",
    "Finalizing Exhaustive Markdown Structure...",
  ];

  useEffect(() => {
    const interval = setInterval(() => {
      setStep((s) => (s < steps.length - 1 ? s + 1 : s));
    }, 3000);
    return () => clearInterval(interval);
  }, []);

  return (
    <div className="max-w-md w-full space-y-8 text-center animate-in fade-in zoom-in duration-500">
      <div className="relative mx-auto w-24 h-24">
        <div className="absolute inset-0 border-2 border-primary/20 rounded-full animate-ping" />
        <div className="absolute inset-2 border-2 border-primary/40 rounded-full animate-pulse" />
        <div className="absolute inset-0 flex items-center justify-center">
          <Sparkles className="h-10 w-10 text-primary animate-bounce" />
        </div>
      </div>
      
      <div className="space-y-3">
        <h2 className="text-xl font-semibold tracking-tight text-white">Expert Agent at Work</h2>
        <div className="h-1.5 w-full bg-slate-800 rounded-full overflow-hidden">
          <div 
            className="h-full bg-primary transition-all duration-1000 ease-out shadow-[0_0_15px_rgba(14,165,233,0.5)]"
            style={{ width: `${((step + 1) / steps.length) * 100}%` }}
          />
        </div>
        <p className="text-sm text-slate-400 animate-pulse min-h-[1.25rem]">
          {steps[step]}
        </p>
      </div>

      <div className="grid grid-cols-2 gap-4 text-left">
        <div className="p-3 rounded-lg bg-slate-900/50 border border-slate-800">
          <p className="text-[10px] uppercase text-slate-500 font-bold mb-1">Source Type</p>
          <p className="text-xs text-slate-200 capitalize">{sourceType}</p>
        </div>
        <div className="p-3 rounded-lg bg-slate-900/50 border border-slate-800">
          <p className="text-[10px] uppercase text-slate-500 font-bold mb-1">Extraction Mode</p>
          <p className="text-xs text-slate-200">Lossless Exhaustive</p>
        </div>
      </div>

      <div className="text-[10px] text-slate-500 uppercase tracking-widest font-medium">
        Advanced Academic Data Recovery in Progress
      </div>
    </div>
  );
}

function Placeholder({ title, desc }: { title: string; desc: string }) {
  return (
    <div className="border border-dashed border-border rounded-xl p-10 text-center">
      <h3 className="font-medium mb-1">{title}</h3>
      <p className="text-sm text-muted-foreground">{desc}</p>
    </div>
  );
}

function DerivativesEmpty({
  kind, noteReady, loading, onGenerate,
}: { kind: "flashcards" | "quiz"; noteReady: boolean; loading: boolean; onGenerate: () => void }) {
  if (!noteReady) {
    return <Placeholder title={`No ${kind} yet`} desc="Generate notes first, then come back here." />;
  }
  return (
    <div className="border border-dashed border-border rounded-xl p-10 text-center space-y-3">
      <h3 className="font-medium">Generate {kind}</h3>
      <p className="text-sm text-muted-foreground">
        We'll use your notes to create {kind === "flashcards" ? "study flashcards" : "a multi-format quiz"}.
      </p>
      <Button onClick={onGenerate} disabled={loading}>
        {loading ? <Loader2 className="h-4 w-4 mr-2 animate-spin" /> : <Sparkles className="h-4 w-4 mr-2" />}
        Generate
      </Button>
    </div>
  );
}
