import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware";
import type { PhotoshootInput, PhotoshootPlan } from "./photoshoot-data";
import type { MoodboardImages } from "./moodboard.functions";

export const generatePlanPdfBase64 = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => z.object({ id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    const { data: row, error } = await context.supabase
      .from("photoshoots")
      .select("title, input, plan, moodboard_images")
      .eq("id", data.id)
      .single();
    if (error) throw new Error(error.message);

    const input = row.input as unknown as PhotoshootInput;
    const plan = row.plan as unknown as PhotoshootPlan;
    const images = (row.moodboard_images as MoodboardImages | null) ?? null;

    const { PDFDocument, StandardFonts, rgb } = await import("pdf-lib");
    const pdf = await PDFDocument.create();
    const font = await pdf.embedFont(StandardFonts.Helvetica);
    const fontBold = await pdf.embedFont(StandardFonts.HelveticaBold);
    const fontItalic = await pdf.embedFont(StandardFonts.HelveticaOblique);

    const PAGE_W = 595.28; // A4
    const PAGE_H = 841.89;
    const MARGIN = 56;
    const TEXT_W = PAGE_W - MARGIN * 2;
    const gold = rgb(0.72, 0.55, 0.27);
    const ink = rgb(0.09, 0.09, 0.1);
    const muted = rgb(0.45, 0.45, 0.5);

    let page = pdf.addPage([PAGE_W, PAGE_H]);
    let y = PAGE_H - MARGIN;

    function newPage() {
      page = pdf.addPage([PAGE_W, PAGE_H]);
      y = PAGE_H - MARGIN;
    }
    function ensure(space: number) { if (y - space < MARGIN) newPage(); }

    function wrap(text: string, maxWidth: number, f: typeof font, size: number): string[] {
      const words = (text || "").split(/\s+/);
      const lines: string[] = [];
      let line = "";
      for (const w of words) {
        const test = line ? `${line} ${w}` : w;
        if (f.widthOfTextAtSize(test, size) > maxWidth) {
          if (line) lines.push(line);
          line = w;
        } else line = test;
      }
      if (line) lines.push(line);
      return lines;
    }
    function drawText(text: string, opts: { size?: number; font?: typeof font; color?: typeof ink; gap?: number; lineHeight?: number } = {}) {
      const size = opts.size ?? 11;
      const f = opts.font ?? font;
      const color = opts.color ?? ink;
      const lh = opts.lineHeight ?? size * 1.45;
      const lines = wrap(text, TEXT_W, f, size);
      for (const line of lines) {
        ensure(lh);
        page.drawText(line, { x: MARGIN, y: y - size, size, font: f, color });
        y -= lh;
      }
      y -= opts.gap ?? 0;
    }
    function eyebrow(text: string) {
      ensure(18);
      page.drawText(text.toUpperCase(), { x: MARGIN, y: y - 9, size: 9, font: fontBold, color: gold });
      y -= 18;
    }
    function h2(text: string) {
      ensure(28);
      drawText(text, { size: 20, font: fontBold, gap: 8 });
    }
    function rule() {
      ensure(14);
      page.drawLine({ start: { x: MARGIN, y }, end: { x: PAGE_W - MARGIN, y }, thickness: 0.5, color: gold });
      y -= 14;
    }

    // Cover
    page.drawRectangle({ x: 0, y: PAGE_H - 220, width: PAGE_W, height: 220, color: rgb(0.97, 0.93, 0.86) });
    y = PAGE_H - 100;
    page.drawText("PHOTOSHOOT PLAN", { x: MARGIN, y, size: 10, font: fontBold, color: gold });
    y -= 36;
    drawText(input.title, { size: 30, font: fontBold, lineHeight: 36 });
    y -= 6;
    drawText(`"${plan.storyTitle}"`, { size: 14, font: fontItalic, color: muted, gap: 24 });

    const metaRow = `${input.eventType}  ·  ${input.emotion}  ·  ${input.personality}  ·  ${input.style}`;
    drawText(metaRow, { size: 10, font: fontBold, color: muted, gap: 24 });
    if (input.date || input.location) {
      drawText(`${input.date || ""}${input.date && input.location ? "  ·  " : ""}${input.location || ""}`, { size: 10, color: muted, gap: 18 });
    }
    rule();

    // Story
    eyebrow("Emotional Strategy");
    h2("The story we're telling");
    drawText(`Goal — ${plan.emotionalGoal}`, { font: fontBold, gap: 6 });
    drawText(`Tone — ${plan.tone}`, { gap: 6 });
    drawText(`Visual theme — ${plan.visualTheme}`, { gap: 14 });
    drawText("Narrative", { size: 9, font: fontBold, color: muted, gap: 4 });
    drawText(plan.storyNarrative, { font: fontItalic, gap: 14 });
    drawText("Visual direction", { size: 9, font: fontBold, color: muted, gap: 4 });
    drawText(plan.visualDirection, { gap: 22 });

    // Palette
    eyebrow("Color Palette");
    h2("The hues of the shoot");
    ensure(80);
    const swatchSize = 70;
    const gap = 8;
    const startX = MARGIN;
    for (let i = 0; i < plan.colorPalette.length; i++) {
      const c = plan.colorPalette[i];
      const hex = (c.hex || "#888888").replace("#", "");
      const r = parseInt(hex.slice(0, 2), 16) / 255 || 0.5;
      const g = parseInt(hex.slice(2, 4), 16) / 255 || 0.5;
      const b = parseInt(hex.slice(4, 6), 16) / 255 || 0.5;
      const x = startX + i * (swatchSize + gap);
      page.drawRectangle({ x, y: y - swatchSize, width: swatchSize, height: swatchSize, color: rgb(r, g, b) });
      page.drawText(c.name.slice(0, 12), { x, y: y - swatchSize - 12, size: 8, font: fontBold, color: ink });
      page.drawText(c.hex, { x, y: y - swatchSize - 22, size: 7, font, color: muted });
    }
    y -= swatchSize + 36;

    // Wardrobe
    eyebrow("Wardrobe");
    h2("What to wear");
    plan.wardrobe.forEach((w, i) => drawText(`${String(i + 1).padStart(2, "0")}.  ${w}`, { gap: 4 }));
    y -= 12;

    // Locations
    eyebrow("Location Engine™");
    h2("Where the story unfolds");
    plan.locations.forEach((l) => {
      drawText(l.name, { font: fontBold, gap: 2 });
      drawText(l.reason, { color: muted, gap: 10 });
    });

    // Shot list
    newPage();
    eyebrow("Shot List");
    h2(`${plan.shotList.length} intentional frames`);
    plan.shotList.forEach((s, i) => drawText(`${String(i + 1).padStart(2, "0")}.  ${s}`, { gap: 3 }));
    y -= 12;

    // AI prompts
    eyebrow("AI Image Prompts");
    h2("Ready for ChatGPT, Midjourney, Flux & Ideogram");
    plan.aiPrompts.forEach((p) => {
      drawText(p.tool.toUpperCase(), { size: 9, font: fontBold, color: gold, gap: 4 });
      drawText(p.prompt, { font: fontItalic, gap: 14 });
    });

    // Moodboard text
    newPage();
    eyebrow("Mood Board");
    h2("The feeling, distilled");
    const mb: { k: string; v: string }[] = [
      { k: "Lighting", v: plan.moodboard.lighting },
      { k: "Wardrobe", v: plan.moodboard.wardrobeStyle },
      { k: "Poses", v: plan.moodboard.poseStyle },
      { k: "Environment", v: plan.moodboard.environment },
    ];
    mb.forEach((m) => {
      drawText(m.k.toUpperCase(), { size: 9, font: fontBold, color: muted, gap: 3 });
      drawText(m.v, { gap: 12 });
    });

    // Moodboard images (if any)
    if (images) {
      const slotOrder: { slot: keyof MoodboardImages; label: string }[] = [
        { slot: "lighting", label: "Lighting" },
        { slot: "wardrobe", label: "Wardrobe" },
        { slot: "pose", label: "Pose" },
        { slot: "environment", label: "Environment" },
      ];
      const present = slotOrder.filter((s) => images[s.slot]);
      if (present.length > 0) {
        newPage();
        eyebrow("Mood Board · Generated");
        h2("Visual references");
        const imgW = (TEXT_W - 12) / 2;
        for (let i = 0; i < present.length; i++) {
          const slot = present[i];
          const b64 = images[slot.slot]!;
          try {
            const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
            const img = await pdf.embedPng(bytes);
            const scale = imgW / img.width;
            const h = img.height * scale;
            ensure(h + 28);
            page.drawImage(img, { x: MARGIN + (i % 2) * (imgW + 12), y: y - h, width: imgW, height: h });
            if (i % 2 === 1 || i === present.length - 1) {
              y -= h + 8;
              page.drawText(slot.label, { x: MARGIN, y: y - 8, size: 8, font: fontBold, color: muted });
              y -= 24;
            }
          } catch {
            // skip bad image
          }
        }
      }
    }

    // Checklist
    newPage();
    eyebrow("Preparation Checklist");
    h2("So nothing is left to chance");
    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" },
    ];
    groups.forEach((g) => {
      drawText(g.label.toUpperCase(), { size: 9, font: fontBold, color: gold, gap: 4 });
      plan.checklist[g.k].forEach((item) => drawText(`•  ${item}`, { gap: 3 }));
      y -= 10;
    });

    // Footer
    ensure(40);
    rule();
    drawText("Personal Photoshoot Studio™ — your photoshoot, intentionally.", { size: 9, color: muted });

    const bytes = await pdf.save();
    // Convert to base64 (safe for any size)
    let binary = "";
    const chunk = 0x8000;
    for (let i = 0; i < bytes.length; i += chunk) {
      binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)) as number[]);
    }
    const base64 = btoa(binary);
    return { base64, filename: `Photography-OS-${(input.title || "plan").replace(/[^a-z0-9]+/gi, "-")}.pdf` };
  });
