import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { useServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { ArrowLeft, BookmarkPlus, Camera, Check, Copy, Download, ImageIcon, LibraryBig, Loader2, Share2, Sparkles, X } from "lucide-react";
import type { PhotoshootInput, PhotoshootPlan } from "@/lib/photoshoot-data";
import { loadInput, loadPlan } from "@/lib/photoshoot-store";
import { getPhotoshoot, savePhotoshoot } from "@/lib/photoshoot.functions";
import { saveMoodboardImage, type MoodboardImages, type MoodboardSlot } from "@/lib/moodboard.functions";
import { togglePublicShare } from "@/lib/sharing.functions";
import { generatePlanPdfBase64 } from "@/lib/pdf.functions";
import { streamImage } from "@/lib/streamImage";
import { useAuth } from "@/hooks/use-auth";
import { toast } from "sonner";

export const Route = createFileRoute("/plan")({
  validateSearch: (s: Record<string, unknown>) =>
    z.object({ id: z.string().uuid().optional() }).parse(s),
  head: () => ({
    meta: [
      { title: "Your photoshoot plan — Personal Photoshoot Studio™" },
      { name: "description", content: "Your generated emotional strategy, story, locations, wardrobe, shot list, AI prompts, mood board, and checklist." },
    ],
  }),
  component: PlanPage,
});

function PlanPage() {
  const navigate = useNavigate();
  const { id } = Route.useSearch();
  const { user } = useAuth();
  const fetchSaved = useServerFn(getPhotoshoot);
  const saveFn = useServerFn(savePhotoshoot);
  const saveImageFn = useServerFn(saveMoodboardImage);
  const toggleShareFn = useServerFn(togglePublicShare);
  const pdfFn = useServerFn(generatePlanPdfBase64);

  const [plan, setPlan] = useState<PhotoshootPlan | null>(null);
  const [input, setInput] = useState<PhotoshootInput | null>(null);
  const [savedId, setSavedId] = useState<string | null>(id ?? null);
  const [saving, setSaving] = useState(false);
  const [moodboardImages, setMoodboardImages] = useState<MoodboardImages>({});
  const [shareSlug, setShareSlug] = useState<string | null>(null);
  const [isPublic, setIsPublic] = useState(false);
  const [pdfLoading, setPdfLoading] = useState(false);

  useEffect(() => {
    let cancelled = false;
    async function run() {
      if (id) {
        try {
          const row = await fetchSaved({ data: { id } });
          if (cancelled) return;
          setInput(row.input);
          setPlan(row.plan);
          setSavedId(row.id);
          setMoodboardImages(row.moodboardImages ?? {});
          setShareSlug(row.shareSlug);
          setIsPublic(row.isPublic);
        } catch {
          navigate({ to: "/library" });
        }
        return;
      }
      const p = loadPlan();
      const i = loadInput();
      if (!p || !i) {
        navigate({ to: "/create" });
        return;
      }
      setPlan(p);
      setInput(i);
    }
    run();
    return () => { cancelled = true; };
  }, [id, fetchSaved, navigate]);

  async function handleSave() {
    if (!input || !plan) return;
    if (!user) {
      toast.message("Sign in to save plans", { description: "Create a free account to keep your library." });
      navigate({ to: "/auth" });
      return;
    }
    setSaving(true);
    try {
      const { id: newId } = await saveFn({ data: { input, plan } });
      setSavedId(newId);
      toast.success("Saved to your library");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Failed to save");
    } finally {
      setSaving(false);
    }
  }

  async function handleToggleShare(makePublic: boolean) {
    if (!savedId) {
      toast.message("Save first", { description: "Sharing needs a saved plan." });
      return;
    }
    try {
      const r = await toggleShareFn({ data: { id: savedId, makePublic } });
      setIsPublic(r.isPublic);
      setShareSlug(r.slug);
      toast.success(makePublic ? "Public link enabled" : "Sharing disabled");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Failed");
    }
  }

  async function handleDownloadPdf() {
    if (!savedId) {
      toast.message("Save first", { description: "PDF needs a saved plan." });
      return;
    }
    setPdfLoading(true);
    try {
      const { base64, filename } = await pdfFn({ data: { id: savedId } });
      const a = document.createElement("a");
      a.href = `data:application/pdf;base64,${base64}`;
      a.download = filename;
      document.body.appendChild(a);
      a.click();
      a.remove();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Failed to generate PDF");
    } finally {
      setPdfLoading(false);
    }
  }

  if (!plan || !input) {
    return (
      <div className="min-h-screen flex items-center justify-center text-muted-foreground">Loading your plan…</div>
    );
  }

  return (
    <div className="min-h-screen bg-background">
      <header className="no-print border-b border-border bg-background/80 backdrop-blur sticky top-0 z-20">
        <div className="mx-auto max-w-6xl px-6 h-16 flex items-center justify-between">
          <Link to="/" className="flex items-center gap-2">
            <div className="h-8 w-8 rounded-full bg-gradient-gold flex items-center justify-center">
              <Camera className="h-4 w-4 text-primary" />
            </div>
            <span className="font-display text-lg font-semibold">Personal Photoshoot Studio<span className="text-gold">™</span></span>
          </Link>
          <div className="flex items-center gap-3">
            {user && (
              <Link to="/library" className="hidden sm:inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground">
                <LibraryBig className="h-4 w-4" /> Library
              </Link>
            )}
            {!id && (
              <Link to="/create" className="inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground">
                <ArrowLeft className="h-4 w-4" /> Edit inputs
              </Link>
            )}
            {!savedId && (
              <button
                onClick={handleSave}
                disabled={saving}
                className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 text-sm font-medium hover:bg-accent transition disabled:opacity-50"
              >
                <BookmarkPlus className="h-4 w-4" /> {saving ? "Saving…" : "Save to library"}
              </button>
            )}
            <button
              onClick={handleDownloadPdf}
              disabled={pdfLoading || !savedId}
              title={!savedId ? "Save the plan first" : "Download as PDF"}
              className="inline-flex items-center gap-2 rounded-full bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 transition disabled:opacity-50"
            >
              {pdfLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Download className="h-4 w-4" />}
              {pdfLoading ? "Building…" : "PDF"}
            </button>
          </div>
        </div>
      </header>

      <main className="mx-auto max-w-5xl px-6 py-12 space-y-12">
        <CoverSection plan={plan} input={input} />
        {savedId && (
          <ShareCard
            slug={shareSlug}
            isPublic={isPublic}
            onToggle={handleToggleShare}
          />
        )}
        <StorySection plan={plan} />
        <div className="grid md:grid-cols-2 gap-6">
          <PaletteCard plan={plan} />
          <MoodboardCard plan={plan} />
        </div>
        <MoodboardImagesCard
          plan={plan}
          input={input}
          savedId={savedId}
          images={moodboardImages}
          onSaved={(slot, b64) => setMoodboardImages((m) => ({ ...m, [slot]: b64 }))}
          saveImage={saveImageFn}
        />
        <WardrobeCard plan={plan} />
        <LocationsCard plan={plan} />
        <ShotListCard plan={plan} />
        <PromptsCard plan={plan} />
        <ChecklistCard plan={plan} />
        <FooterCTA />
      </main>
    </div>
  );
}

function ShareCard({ slug, isPublic, onToggle }: { slug: string | null; isPublic: boolean; onToggle: (next: boolean) => void }) {
  const [copied, setCopied] = useState(false);
  const url = slug && typeof window !== "undefined" ? `${window.location.origin}/p/${slug}` : "";
  return (
    <section className="rounded-2xl border border-border bg-card p-6 md:p-8 flex flex-col md:flex-row md:items-center justify-between gap-4">
      <div className="flex items-start gap-3">
        <div className="h-10 w-10 rounded-full bg-gradient-gold flex items-center justify-center shrink-0"><Share2 className="h-4 w-4 text-primary" /></div>
        <div>
          <p className="font-display text-lg leading-tight">Public share link</p>
          <p className="text-sm text-muted-foreground">{isPublic ? "Anyone with the link can view this plan." : "Off — only you can see this plan."}</p>
        </div>
      </div>
      <div className="flex items-center gap-2 flex-wrap">
        {isPublic && url && (
          <>
            <input readOnly value={url} className="rounded-lg border border-input bg-background px-3 py-2 text-xs font-mono w-72 max-w-full" />
            <button
              onClick={() => { navigator.clipboard.writeText(url); setCopied(true); toast.success("Link copied"); setTimeout(() => setCopied(false), 1500); }}
              className="inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-2 text-xs font-medium hover:bg-accent"
            >
              {copied ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />} {copied ? "Copied" : "Copy"}
            </button>
          </>
        )}
        <button
          onClick={() => onToggle(!isPublic)}
          className={`inline-flex items-center gap-1.5 rounded-full px-4 py-2 text-xs font-medium transition ${isPublic ? "border border-border hover:bg-accent" : "bg-primary text-primary-foreground hover:opacity-90"}`}
        >
          {isPublic ? <><X className="h-3.5 w-3.5" /> Stop sharing</> : <><Share2 className="h-3.5 w-3.5" /> Enable share link</>}
        </button>
      </div>
    </section>
  );
}

const MOODBOARD_SLOTS: { slot: MoodboardSlot; label: string; field: keyof PhotoshootPlan["moodboard"] }[] = [
  { slot: "lighting", label: "Lighting", field: "lighting" },
  { slot: "wardrobe", label: "Wardrobe", field: "wardrobeStyle" },
  { slot: "pose", label: "Pose", field: "poseStyle" },
  { slot: "environment", label: "Environment", field: "environment" },
];

function MoodboardImagesCard({
  plan, input, savedId, images, onSaved, saveImage,
}: {
  plan: PhotoshootPlan;
  input: PhotoshootInput;
  savedId: string | null;
  images: MoodboardImages;
  onSaved: (slot: MoodboardSlot, b64: string) => void;
  saveImage: (args: { data: { photoshootId: string; slot: MoodboardSlot; imageB64: string } }) => Promise<unknown>;
}) {
  const [busy, setBusy] = useState<MoodboardSlot | null>(null);
  const [previews, setPreviews] = useState<Partial<Record<MoodboardSlot, { url: string; isFinal: boolean }>>>({});

  async function generate(slot: MoodboardSlot, field: keyof PhotoshootPlan["moodboard"]) {
    const prompt = `${input.style} photography moodboard reference image. ${plan.visualDirection} ${plan.moodboard[field]} Color palette: ${plan.colorPalette.map((c) => c.name).join(", ")}. Cinematic, editorial, ${input.emotion.toLowerCase()} feeling. No text, no logos, no watermarks.`;
    setBusy(slot);
    setPreviews((p) => ({ ...p, [slot]: undefined }));
    try {
      let lastB64 = "";
      await streamImage("/api/generate-moodboard-image", { prompt }, (dataUrl, isFinal, rawB64) => {
        setPreviews((p) => ({ ...p, [slot]: { url: dataUrl, isFinal } }));
        if (isFinal) lastB64 = rawB64;
      });
      if (savedId && lastB64) {
        await saveImage({ data: { photoshootId: savedId, slot, imageB64: lastB64 } });
        onSaved(slot, lastB64);
        toast.success(`${slot} image saved`);
      } else if (!savedId && lastB64) {
        onSaved(slot, lastB64);
        toast.message("Image generated", { description: "Save the plan to keep it." });
      }
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Image generation failed");
    } finally {
      setBusy(null);
    }
  }

  return (
    <Section eyebrow="Mood Board · AI References" title="Generate visual references">
      <p className="text-sm text-muted-foreground mb-6">Render four AI-generated moodboard frames — one per facet. Streamed live; saved with your plan.</p>
      <div className="grid sm:grid-cols-2 md:grid-cols-4 gap-4">
        {MOODBOARD_SLOTS.map(({ slot, label, field }) => {
          const saved = images[slot];
          const preview = previews[slot];
          const src = preview?.url || (saved ? `data:image/png;base64,${saved}` : null);
          const isBusy = busy === slot;
          return (
            <div key={slot} className="space-y-2">
              <div className="aspect-square rounded-xl border border-border bg-muted overflow-hidden relative">
                {src ? (
                  <img
                    src={src}
                    alt={label}
                    className="w-full h-full object-cover transition-[filter] duration-300"
                    style={{ filter: preview && !preview.isFinal ? "blur(16px)" : "none" }}
                  />
                ) : (
                  <div className="absolute inset-0 grid place-items-center text-muted-foreground">
                    <ImageIcon className="h-8 w-8 opacity-40" />
                  </div>
                )}
                {isBusy && (
                  <div className="absolute top-2 right-2 bg-background/80 backdrop-blur rounded-full p-1.5">
                    <Loader2 className="h-3.5 w-3.5 animate-spin text-gold" />
                  </div>
                )}
              </div>
              <p className="text-[10px] uppercase tracking-[0.25em] text-muted-foreground">{label}</p>
              <button
                onClick={() => generate(slot, field)}
                disabled={isBusy}
                className="w-full text-xs rounded-full border border-border px-3 py-1.5 hover:bg-accent disabled:opacity-50"
              >
                {isBusy ? "Generating…" : src ? "Regenerate" : "Generate"}
              </button>
            </div>
          );
        })}
      </div>
    </Section>
  );
}

function Section({ eyebrow, title, children, className = "" }: { eyebrow: string; title: string; children: React.ReactNode; className?: string }) {
  return (
    <section className={`rounded-2xl border border-border bg-card p-8 md:p-10 shadow-soft print-card ${className}`}>
      <p className="text-xs uppercase tracking-[0.3em] text-gold mb-2">{eyebrow}</p>
      <h2 className="font-display text-3xl md:text-4xl leading-tight mb-6">{title}</h2>
      {children}
    </section>
  );
}

function CoverSection({ plan, input }: { plan: PhotoshootPlan; input: PhotoshootInput }) {
  return (
    <section className="relative overflow-hidden rounded-3xl border border-border bg-gradient-warm p-10 md:p-16 shadow-elegant print-card">
      <div className="absolute -top-24 -right-24 h-72 w-72 rounded-full bg-gold/30 blur-3xl no-print" />
      <p className="text-xs uppercase tracking-[0.3em] text-gold mb-4">Photoshoot Plan</p>
      <h1 className="font-display text-5xl md:text-7xl leading-[1.04] text-balance max-w-3xl">{input.title}</h1>
      <p className="mt-6 text-lg md:text-xl text-foreground/80 italic font-display">"{plan.storyTitle}"</p>
      <div className="mt-8 grid grid-cols-2 md:grid-cols-4 gap-6 max-w-3xl">
        <Meta k="Event" v={input.eventType} />
        <Meta k="Emotion" v={input.emotion} />
        <Meta k="Personality" v={input.personality} />
        <Meta k="Style" v={input.style} />
      </div>
    </section>
  );
}

function Meta({ k, v }: { k: string; v: string }) {
  return (
    <div>
      <p className="text-[10px] uppercase tracking-[0.25em] text-muted-foreground mb-1">{k}</p>
      <p className="font-display text-xl">{v}</p>
    </div>
  );
}

function StorySection({ plan }: { plan: PhotoshootPlan }) {
  return (
    <Section eyebrow="Emotional Strategy" title="The story we're telling">
      <div className="grid md:grid-cols-3 gap-6 mb-8">
        <Stat label="Emotional Goal" value={plan.emotionalGoal} />
        <Stat label="Tone" value={plan.tone} />
        <Stat label="Visual Theme" value={plan.visualTheme} />
      </div>
      <div className="space-y-5">
        <div>
          <p className="text-xs uppercase tracking-[0.2em] text-muted-foreground mb-2">Narrative</p>
          <p className="text-lg leading-relaxed font-display italic">{plan.storyNarrative}</p>
        </div>
        <div>
          <p className="text-xs uppercase tracking-[0.2em] text-muted-foreground mb-2">Visual Direction</p>
          <p className="leading-relaxed text-foreground/85">{plan.visualDirection}</p>
        </div>
      </div>
    </Section>
  );
}

function Stat({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-xl border border-border bg-background p-5">
      <p className="text-[10px] uppercase tracking-[0.25em] text-gold mb-1">{label}</p>
      <p className="font-display text-lg leading-snug">{value}</p>
    </div>
  );
}

function PaletteCard({ plan }: { plan: PhotoshootPlan }) {
  return (
    <Section eyebrow="Color Palette" title="The hues of the shoot">
      <div className="grid grid-cols-5 gap-2 mb-4">
        {plan.colorPalette.map((c) => (
          <div key={c.hex + c.name} className="space-y-2">
            <div className="aspect-square rounded-lg border border-border shadow-soft" style={{ backgroundColor: c.hex }} />
            <p className="text-xs font-medium truncate" title={c.name}>{c.name}</p>
            <p className="text-[10px] uppercase tracking-wider text-muted-foreground">{c.hex}</p>
          </div>
        ))}
      </div>
    </Section>
  );
}

function MoodboardCard({ plan }: { plan: PhotoshootPlan }) {
  const items = [
    { k: "Lighting", v: plan.moodboard.lighting },
    { k: "Wardrobe", v: plan.moodboard.wardrobeStyle },
    { k: "Poses", v: plan.moodboard.poseStyle },
    { k: "Environment", v: plan.moodboard.environment },
  ];
  return (
    <Section eyebrow="Mood Board" title="The feeling, distilled">
      <ul className="space-y-4">
        {items.map((i) => (
          <li key={i.k} className="border-l-2 border-gold pl-4">
            <p className="text-[10px] uppercase tracking-[0.25em] text-muted-foreground mb-1">{i.k}</p>
            <p className="text-sm leading-relaxed">{i.v}</p>
          </li>
        ))}
      </ul>
    </Section>
  );
}

function WardrobeCard({ plan }: { plan: PhotoshootPlan }) {
  return (
    <Section eyebrow="Wardrobe" title="What to wear">
      <ul className="grid sm:grid-cols-2 gap-3">
        {plan.wardrobe.map((w, i) => (
          <li key={i} className="flex gap-3 rounded-lg border border-border bg-background p-4">
            <span className="font-display text-gold text-lg leading-none">{String(i + 1).padStart(2, "0")}</span>
            <span className="text-sm leading-relaxed">{w}</span>
          </li>
        ))}
      </ul>
    </Section>
  );
}

function LocationsCard({ plan }: { plan: PhotoshootPlan }) {
  return (
    <Section eyebrow="Location Engine™" title="Where the story unfolds">
      <ul className="grid sm:grid-cols-2 gap-4">
        {plan.locations.map((l, i) => (
          <li key={i} className="rounded-xl border border-border bg-background p-5">
            <p className="font-display text-xl mb-1">{l.name}</p>
            <p className="text-sm text-muted-foreground leading-relaxed">{l.reason}</p>
          </li>
        ))}
      </ul>
    </Section>
  );
}

function ShotListCard({ plan }: { plan: PhotoshootPlan }) {
  return (
    <Section eyebrow="Shot List" title={`${plan.shotList.length} intentional frames`}>
      <ol className="grid sm:grid-cols-2 gap-x-8 gap-y-2.5">
        {plan.shotList.map((s, i) => (
          <li key={i} className="flex gap-3 text-sm">
            <span className="font-display text-gold w-7 shrink-0">{String(i + 1).padStart(2, "0")}</span>
            <span className="leading-relaxed">{s}</span>
          </li>
        ))}
      </ol>
    </Section>
  );
}

function PromptsCard({ plan }: { plan: PhotoshootPlan }) {
  return (
    <Section eyebrow="AI Image Prompts" title="Ready for ChatGPT, Midjourney, Flux & Ideogram">
      <div className="space-y-4">
        {plan.aiPrompts.map((p) => (
          <PromptBlock key={p.tool} tool={p.tool} prompt={p.prompt} />
        ))}
      </div>
    </Section>
  );
}

function PromptBlock({ tool, prompt }: { tool: string; prompt: string }) {
  const [copied, setCopied] = useState(false);
  return (
    <div className="rounded-xl border border-border bg-background p-5">
      <div className="flex items-start justify-between gap-4 mb-3">
        <div className="flex items-center gap-2">
          <Sparkles className="h-3.5 w-3.5 text-gold" />
          <p className="text-xs uppercase tracking-[0.25em] font-medium">{tool}</p>
        </div>
        <button
          onClick={() => {
            navigator.clipboard.writeText(prompt);
            setCopied(true);
            toast.success(`${tool} prompt copied`);
            setTimeout(() => setCopied(false), 1500);
          }}
          className="no-print inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground"
        >
          <Copy className="h-3 w-3" /> {copied ? "Copied" : "Copy"}
        </button>
      </div>
      <p className="text-sm leading-relaxed font-display italic">"{prompt}"</p>
    </div>
  );
}

function ChecklistCard({ plan }: { plan: PhotoshootPlan }) {
  const groups: { k: keyof PhotoshootPlan["checklist"]; label: string }[] = [
    { k: "wardrobe", label: "Wardrobe" },
    { k: "props", label: "Props" },
    { k: "makeupHair", label: "Makeup & Hair" },
    { k: "logistics", label: "Logistics" },
    { k: "backupPlan", label: "Backup Plan" },
    { k: "weather", label: "Weather" },
  ];
  return (
    <Section eyebrow="Preparation Checklist" title="So nothing is left to chance">
      <div className="grid sm:grid-cols-2 gap-6">
        {groups.map((g) => (
          <div key={g.k}>
            <p className="text-xs uppercase tracking-[0.25em] text-gold mb-3">{g.label}</p>
            <ul className="space-y-2">
              {plan.checklist[g.k].map((item, i) => (
                <li key={i} className="flex gap-2.5 text-sm">
                  <span className="mt-1.5 h-1.5 w-1.5 rounded-full bg-gold shrink-0" />
                  <span className="leading-relaxed">{item}</span>
                </li>
              ))}
            </ul>
          </div>
        ))}
      </div>
    </Section>
  );
}

function FooterCTA() {
  return (
    <div className="no-print text-center py-8">
      <Link to="/create" className="inline-flex items-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground underline underline-offset-4 decoration-gold decoration-2">
        Design another photoshoot
      </Link>
    </div>
  );
}
