import { NextRequest, NextResponse } from "next/server";
import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
import {
  getSurveyAnalytics,
  parseAnalyticsFilters,
} from "@/lib/queries/analytics-queries";
import { requireSurveyExportAccess } from "@/lib/auth/require-survey-export";
import { formatCount, formatPercent } from "@/lib/utils/analytics-format";

interface RouteParams {
  params: { surveyId: string };
}

const PAGE_WIDTH = 612;
const PAGE_HEIGHT = 792;
const MARGIN = 48;
const LINE_HEIGHT = 14;

/** Strip/replace chars that WinAnsi Helvetica cannot encode. */
function pdfSafeText(text: string): string {
  return text
    .replace(/\u2014/g, "-")
    .replace(/\u2013/g, "-")
    .replace(/\u2018|\u2019/g, "'")
    .replace(/\u201C|\u201D/g, '"')
    .replace(/[^\x09\x0A\x0D\x20-\x7E]/g, "?");
}

function wrapText(text: string, maxChars: number): string[] {
  const safe = pdfSafeText(text);
  const words = safe.split(/\s+/);
  const lines: string[] = [];
  let line = "";

  for (const word of words) {
    const next = line ? `${line} ${word}` : word;
    if (next.length > maxChars && line) {
      lines.push(line);
      line = word;
    } else {
      line = next;
    }
  }
  if (line) lines.push(line);
  return lines.length ? lines : [""];
}

export async function GET(request: NextRequest, { params }: RouteParams) {
  const access = await requireSurveyExportAccess(params.surveyId);
  if ("error" in access) {
    return NextResponse.json({ error: access.error }, { status: access.status });
  }

  const filters = parseAnalyticsFilters(
    Object.fromEntries(request.nextUrl.searchParams.entries())
  );

  const analytics = await getSurveyAnalytics(
    params.surveyId,
    access.workspaceId,
    filters
  );

  if (!analytics) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }

  const pdf = await PDFDocument.create();
  const font = await pdf.embedFont(StandardFonts.Helvetica);
  const fontBold = await pdf.embedFont(StandardFonts.HelveticaBold);

  let page = pdf.addPage([PAGE_WIDTH, PAGE_HEIGHT]);
  let y = PAGE_HEIGHT - MARGIN;

  function ensureSpace(lines = 1) {
    if (y - lines * LINE_HEIGHT < MARGIN) {
      page = pdf.addPage([PAGE_WIDTH, PAGE_HEIGHT]);
      y = PAGE_HEIGHT - MARGIN;
    }
  }

  function drawLine(text: string, bold = false, size = 11) {
    ensureSpace(2);
    page.drawText(pdfSafeText(text), {
      x: MARGIN,
      y,
      size,
      font: bold ? fontBold : font,
      color: rgb(0.08, 0.15, 0.27),
    });
    y -= LINE_HEIGHT + (size > 11 ? 4 : 0);
  }

  drawLine("SurveyStronghold - Analytics Report", true, 16);
  y -= 4;
  drawLine(analytics.surveyTitle, true, 13);
  drawLine(
    `Generated ${new Date().toLocaleString("en-US")} | Filter: ${filters.dateRange}, ${filters.status}`,
    false,
    9
  );
  y -= 8;

  drawLine("Overview", true, 12);
  drawLine(`Total views: ${formatCount(analytics.overview.totalViews)}`);
  drawLine(`Responses: ${formatCount(analytics.overview.responses)}`);
  drawLine(
    `Completion rate: ${formatPercent(analytics.overview.completionRate)}`
  );
  drawLine(`Avg. time: ${analytics.overview.avgTimeToComplete}`);
  y -= 8;

  drawLine("Traffic sources", true, 12);
  if (analytics.trafficSources.length === 0) {
    drawLine("No traffic data.");
  } else {
    for (const src of analytics.trafficSources) {
      drawLine(`${src.name}: ${src.value}`);
    }
  }
  y -= 8;

  drawLine("Question summaries", true, 12);
  analytics.questions.forEach((q, i) => {
    ensureSpace(4);
    const header = `Q${i + 1}. ${q.title}`;
    for (const line of wrapText(header, 70)) {
      drawLine(line, true, 10);
    }
    drawLine(`${q.responseCount} responses`, false, 9);

    if (q.kind === "nps") {
      drawLine(`NPS Score: ${q.npsScore}`, false, 9);
      for (const d of q.distribution.filter((x) => x.count > 0)) {
        drawLine(`  Score ${d.score}: ${d.count}`, false, 9);
      }
    } else if (q.kind === "rating") {
      drawLine(`Average: ${q.average}`, false, 9);
    } else if (q.kind === "choice") {
      for (const c of q.choices.slice(0, 8)) {
        drawLine(`  ${c.label}: ${c.count} (${c.percent}%)`, false, 9);
      }
    } else if (q.kind === "open_text") {
      const top = q.words.slice(0, 10).map((w) => w.word).join(", ");
      for (const line of wrapText(`Top words: ${top || "-"}`, 72)) {
        drawLine(line, false, 9);
      }
    }
    y -= 4;
  });

  const pdfBytes = await pdf.save();
  const filename = `survey-${params.surveyId.slice(0, 8)}-report.pdf`;

  return new NextResponse(Buffer.from(pdfBytes), {
    headers: {
      "Content-Type": "application/pdf",
      "Content-Disposition": `attachment; filename="${filename}"`,
    },
  });
}
