/**
 * POST /api/billing/pdf
 *
 * Premium-only: render a luận-giải PDF for the user's chart + a list of
 * pre-fetched section bodies (so we don't re-stream from the AI provider
 * — the client passes whatever it has displayed and the PDF reflects
 * exactly that).
 *
 * Body:
 *   {
 *     input: ChartInput,
 *     forDate?: "YYYY-MM-DD",
 *     sections: Array<{ key: SectionKey, title: string, body: string }>
 *   }
 *
 * Behaviour:
 *   - Anonymous → 401
 *   - FREE plan  → 402 with hint to /pricing
 *   - PREMIUM    → 200 application/pdf, attachment filename includes name
 *
 * Why React-PDF over Puppeteer: no headless Chrome dep, ~50ms render,
 * font is bundled, fits Next.js standalone runtime.
 */
import { NextRequest } from "next/server";
import { renderToBuffer } from "@react-pdf/renderer";
import { buildChart, type ChartInput } from "@/lib/tuvi/engine";
import { buildHoroscope } from "@/lib/tuvi/horoscope";
import { currentUser } from "@/lib/charts";
import { prisma } from "@/lib/db";
import { resolvePlan } from "@/lib/billing/plans";
import { ReportDocument, type SectionContent } from "@/lib/billing/pdf-report";
import { SECTIONS, type SectionKey } from "@/lib/ai/section-prompts";

export const runtime = "nodejs";

type Body = {
  input?: ChartInput;
  forDate?: string;
  sections?: SectionContent[];
};

const VALID_KEYS = new Set<SectionKey>(SECTIONS.map((s) => s.key));

function jsonError(msg: string, status: number) {
  return new Response(JSON.stringify({ error: msg }), {
    status,
    headers: { "Content-Type": "application/json" },
  });
}

export async function POST(req: NextRequest) {
  // Auth gate
  const me = await currentUser();
  if (!me) return jsonError("Bạn cần đăng nhập để xuất PDF.", 401);

  const u = await prisma.user.findUnique({
    where: { id: me.id },
    select: { plan: true, name: true },
  });
  const plan = resolvePlan(u?.plan);
  if (!plan.limits.pdfExport) {
    return jsonError("Xuất PDF luận giải là tính năng Premium. Nâng cấp tại /pricing.", 402);
  }

  // Body parse + validate
  let body: Body;
  try {
    body = (await req.json()) as Body;
  } catch {
    return jsonError("Invalid JSON body", 400);
  }
  if (!body.input) return jsonError("Thiếu input lá số.", 400);
  if (!Array.isArray(body.sections) || body.sections.length === 0) {
    return jsonError("Cần ít nhất 1 mục đã đọc.", 400);
  }
  // Sanitize sections — only keep valid keys, cap body length
  const cleanSections: SectionContent[] = [];
  for (const s of body.sections) {
    if (!s || typeof s !== "object") continue;
    if (!VALID_KEYS.has(s.key)) continue;
    cleanSections.push({
      key: s.key,
      title: String(s.title || s.key).slice(0, 100),
      body: String(s.body || "").slice(0, 5000),
    });
  }
  if (cleanSections.length === 0) {
    return jsonError("Không có mục hợp lệ.", 400);
  }

  // Build chart + (optional) horoscope
  let chart;
  try {
    chart = buildChart(body.input);
  } catch (e) {
    return jsonError(e instanceof Error ? e.message : "Không an được lá số.", 400);
  }

  let horoscope = null;
  try {
    horoscope = buildHoroscope(body.input, body.forDate);
  } catch {
    horoscope = null;
  }

  // Render PDF
  const pdfBuffer = await renderToBuffer(
    ReportDocument({
      chart,
      horoscope,
      sections: cleanSections,
      noWatermark: plan.limits.noWatermark,
      generatedAt: new Date().toISOString(),
    })
  );

  // Filename: ASCII-safe slug of the chart name
  const slug =
    (chart.fullName || u?.name || "la-so")
      .toLowerCase()
      .normalize("NFD")
      .replace(/[\u0300-\u036f]/g, "")
      .replace(/đ/g, "d")
      .replace(/[^a-z0-9]+/g, "-")
      .replace(/^-+|-+$/g, "")
      .slice(0, 60) || "la-so";
  const filename = `tuviso-${slug}-${chart.solarDate}.pdf`;

  return new Response(pdfBuffer as unknown as BodyInit, {
    status: 200,
    headers: {
      "Content-Type": "application/pdf",
      "Content-Disposition": `attachment; filename="${filename}"`,
      "Cache-Control": "no-store",
    },
  });
}
