// server/services/exportTemplates.ts
import PDFDocument from "pdfkit";
import { Document, Packer, Paragraph, HeadingLevel, TextRun, Table, TableRow, TableCell, AlignmentType, PageBreak } from "docx";

export type PlanMode = "lean" | "full";
export type PlanSection = { id: string; title: string; content: string };
export type PlanResponse = {
  mode: PlanMode;
  sections: PlanSection[];
  finance?: {
    assumptions: string[];
    monthly_table?: Array<{ month: string; revenue: number; costs: number; profit: number }>;
  };
};

export type ExportMeta = {
  businessName: string; // inferred from first/exec section if you store it elsewhere, pass in here
  subtitle?: string;    // e.g., "Business Plan"
  generatedAt?: Date;
};

const DEFAULTS = {
  titleFontSize: 22,
  h2Size: 16,
  bodySize: 11,
  primaryHex: "#0b6fa4",
  textHex: "#222222",
};

function splitLines(text: string, width: number): string[] {
  // very simple reflow helper (server monospace-like wrap). PDFKit handles wrapping but we pre-split for consistency if needed.
  const lines: string[] = [];
  const words = text.split(/\s+/);
  let buf: string[] = [];
  for (const w of words) {
    const test = [...buf, w].join(" ");
    if (test.length > width) {
      if (buf.length) lines.push(buf.join(" "));
      buf = [w];
    } else {
      buf.push(w);
    }
  }
  if (buf.length) lines.push(buf.join(" "));
  return lines;
}

/* =========================
   PDF GENERATION
   ========================= */
export function renderPlanPDF(plan: PlanResponse, meta: ExportMeta): PDFDocument {
  const doc = new PDFDocument({
    size: "LETTER",
    margins: { top: 72, bottom: 72, left: 72, right: 72 },
    info: {
      Title: `${meta.businessName} — ${meta.subtitle ?? "Business Plan"}`,
      Author: "IBrandBiz",
      Subject: "Business Plan",
      Creator: "IBrandBiz Export Service",
      Producer: "PDFKit",
    },
  });

  // Cover
  doc.fillColor(DEFAULTS.primaryHex);
  doc.fontSize(28).font("Helvetica-Bold").text(meta.businessName, { align: "center" });
  doc.moveDown(0.3);
  doc.fontSize(14).font("Helvetica").fillColor(DEFAULTS.textHex).text(meta.subtitle ?? "Business Plan", { align: "center" });
  doc.moveDown(1);
  doc.fontSize(10).fillColor("#666666").text(`Generated: ${new Date(meta.generatedAt ?? new Date()).toLocaleString()}`, { align: "center" });

  // Little accent bar
  doc.moveDown(2);
  const mid = doc.page.width / 2 - 100;
  doc.rect(mid, doc.y, 200, 4).fill(DEFAULTS.primaryHex);
  doc.fillColor(DEFAULTS.textHex);

  // New page
  doc.addPage();

  // TOC (Full only)
  if (plan.mode === "full") {
    doc.fontSize(18).font("Helvetica-Bold").fillColor(DEFAULTS.primaryHex).text("Table of Contents");
    doc.moveDown(0.75);
    doc.fontSize(11).font("Helvetica").fillColor(DEFAULTS.textHex);

    plan.sections.forEach((s, idx) => {
      doc.text(`${idx + 1}. ${s.title}`);
    });

    doc.addPage();
  }

  // Sections
  plan.sections.forEach((s, idx) => {
    if (idx > 0) doc.moveDown(0.5);
    doc.fontSize(DEFAULTS.h2Size).font("Helvetica-Bold").fillColor(DEFAULTS.primaryHex).text(s.title);
    doc.moveDown(0.2);
    doc.fontSize(DEFAULTS.bodySize).font("Helvetica").fillColor(DEFAULTS.textHex);

    // Simple bullet parsing: treat lines starting with "-" or "•" as bullets
    const lines = s.content.split(/\r?\n/).filter(Boolean);
    if (lines.some(l => /^(\-|\•)\s+/.test(l))) {
      doc.moveDown(0.2);
      lines.forEach(l => {
        const m = l.match(/^(\-|\•)\s+(.*)$/);
        if (m) {
          doc.circle(doc.x + 3, doc.y + 6, 2).fill(DEFAULTS.primaryHex).fillColor(DEFAULTS.textHex);
          doc.text(m[2], doc.x + 12, doc.y - 6, { width: 450 });
          doc.moveDown(0.2);
        } else {
          doc.text(l, { width: 470 });
        }
      });
    } else {
      doc.text(s.content, { width: 470 });
    }

    // Finance after sections in Full mode
    if (plan.mode === "full" && idx === plan.sections.length - 1 && plan.finance) {
      doc.addPage();
      doc.fontSize(DEFAULTS.h2Size).font("Helvetica-Bold").fillColor(DEFAULTS.primaryHex).text("Financial Snapshot");
      doc.moveDown(0.3);
      if (plan.finance.assumptions?.length) {
        doc.fontSize(DEFAULTS.bodySize).font("Helvetica").fillColor(DEFAULTS.textHex).text("Assumptions:");
        doc.moveDown(0.2);
        plan.finance.assumptions.forEach(a => {
          doc.circle(doc.x + 3, doc.y + 6, 2).fill(DEFAULTS.primaryHex).fillColor(DEFAULTS.textHex);
          doc.text(a, doc.x + 12, doc.y - 6, { width: 470 });
          doc.moveDown(0.1);
        });
        doc.moveDown(0.5);
      }

      if (plan.finance.monthly_table?.length) {
        // Simple table
        const header = ["Month", "Revenue", "Costs", "Profit"];
        const rows = plan.finance.monthly_table.map(r => [
          r.month,
          `$${r.revenue.toLocaleString()}`,
          `$${r.costs.toLocaleString()}`,
          `$${r.profit.toLocaleString()}`
        ]);

        const colWidths = [90, 120, 120, 120];
        const startX = doc.x;
        let y = doc.y;

        // Header
        doc.font("Helvetica-Bold").fillColor(DEFAULTS.primaryHex);
        header.forEach((h, i) => doc.text(h, startX + colWidths.slice(0, i).reduce((a, b) => a + b, 0), y, { width: colWidths[i] }));
        y += 18;

        // Rows
        doc.font("Helvetica").fillColor(DEFAULTS.textHex);
        rows.forEach((row) => {
          row.forEach((cell, i) => {
            doc.text(cell, startX + colWidths.slice(0, i).reduce((a, b) => a + b, 0), y, { width: colWidths[i] });
          });
          y += 16;
          if (y > doc.page.height - 72) { doc.addPage(); y = doc.y; }
        });
      }
    }

    // Page break between sections if getting too long
    if (doc.y > doc.page.height - 120 && idx < plan.sections.length - 1) {
      doc.addPage();
    }
  });

  return doc;
}

/* =========================
   DOCX GENERATION
   ========================= */
export async function renderPlanDOCX(plan: PlanResponse, meta: ExportMeta): Promise<Buffer> {
  const children: any[] = [];

  // Cover
  children.push(
    new Paragraph({
      alignment: AlignmentType.CENTER,
      spacing: { after: 200 },
      children: [
        new TextRun({ text: meta.businessName, bold: true, size: 48, color: "0B6FA4" }),
      ],
    }),
    new Paragraph({
      alignment: AlignmentType.CENTER,
      spacing: { after: 200 },
      children: [ new TextRun({ text: meta.subtitle ?? "Business Plan", size: 24 }) ],
    }),
    new Paragraph({
      alignment: AlignmentType.CENTER,
      spacing: { after: 400 },
      children: [ new TextRun({ text: `Generated: ${new Date(meta.generatedAt ?? new Date()).toLocaleString()}`, size: 18, color: "666666" }) ],
    }),
    new Paragraph({ children: [ new PageBreak() ] })
  );

  // TOC (full only): Simple faux TOC (Docx built-in TOC requires field codes & user update)
  if (plan.mode === "full") {
    children.push(new Paragraph({ text: "Table of Contents", heading: HeadingLevel.HEADING_1 }));
    plan.sections.forEach((s, idx) => {
      children.push(new Paragraph({ text: `${idx + 1}. ${s.title}`, spacing: { after: 120 } }));
    });
    children.push(new Paragraph({ children: [ new PageBreak() ] }));
  }

  // Sections
  for (const s of plan.sections) {
    children.push(new Paragraph({ text: s.title, heading: HeadingLevel.HEADING_2 }));

    // Bullet vs paragraph
    const lines = s.content.split(/\r?\n/).filter(Boolean);
    if (lines.some(l => /^(\-|\•)\s+/.test(l))) {
      for (const l of lines) {
        const m = l.match(/^(\-|\•)\s+(.*)$/);
        if (m) {
          children.push(new Paragraph({
            bullet: { level: 0 },
            children: [ new TextRun({ text: m[2], size: 22 }) ],
            spacing: { after: 60 },
          }));
        } else {
          children.push(new Paragraph({ text: l, spacing: { after: 120 } }));
        }
      }
    } else {
      children.push(new Paragraph({ text: s.content, spacing: { after: 200 } }));
    }
  }

  // Finance (full only)
  if (plan.mode === "full" && plan.finance) {
    children.push(new Paragraph({ children: [ new PageBreak() ] }));
    children.push(new Paragraph({ text: "Financial Snapshot", heading: HeadingLevel.HEADING_2 }));

    if (plan.finance.assumptions?.length) {
      children.push(new Paragraph({ text: "Assumptions", heading: HeadingLevel.HEADING_3 }));
      for (const a of plan.finance.assumptions) {
        children.push(new Paragraph({ bullet: { level: 0 }, children: [ new TextRun({ text: a }) ] }));
      }
    }

    if (plan.finance.monthly_table?.length) {
      const header = ["Month", "Revenue", "Costs", "Profit"];
      const tableRows: TableRow[] = [];

      // Header row
      tableRows.push(new TableRow({
        children: header.map(h => new TableCell({
          children: [ new Paragraph({ text: h }) ],
        }))
      }));

      // Data rows
      for (const r of plan.finance.monthly_table) {
        tableRows.push(new TableRow({
          children: [
            new TableCell({ children: [ new Paragraph({ text: r.month }) ] }),
            new TableCell({ children: [ new Paragraph({ text: `$${r.revenue.toLocaleString()}` }) ] }),
            new TableCell({ children: [ new Paragraph({ text: `$${r.costs.toLocaleString()}` }) ] }),
            new TableCell({ children: [ new Paragraph({ text: `$${r.profit.toLocaleString()}` }) ] }),
          ]
        }));
      }

      children.push(new Paragraph({ text: "Monthly Table", heading: HeadingLevel.HEADING_3 }));
      children.push(new Table({ rows: tableRows, width: { size: 100, type: "pct" } }));
    }
  }

  const doc = new Document({ sections: [{ properties: {}, children }] });
  const buffer = await Packer.toBuffer(doc);
  return buffer;
}
