import { NextResponse } from "next/server";
import { canCompany } from "@/lib/company-context";
import { registerReportAuditLog } from "@/lib/reports/audit";
import { montarArquivoDoRelatorio } from "@/lib/reports/exportar";
import { createClient } from "@/lib/supabase-server";
import { createReportRuntime, runReport } from "@/lib/reports/service";
import type { ReportRequest } from "@/lib/reports/contracts";

function normalizeRequest(body: Record<string, unknown>): ReportRequest {
  return {
    tab: typeof body.tab === "string" ? (body.tab as ReportRequest["tab"]) : "financial",
    filters: body.filters && typeof body.filters === "object" ? (body.filters as ReportRequest["filters"]) : {},
    page: 1,
    pageSize: typeof body.pageSize === "number" ? body.pageSize : 5000,
    search: typeof body.search === "string" ? body.search : "",
    sort: body.sort && typeof body.sort === "object" ? (body.sort as ReportRequest["sort"]) : null,
    visibleColumnIds: Array.isArray(body.visibleColumnIds)
      ? body.visibleColumnIds.filter((item): item is string => typeof item === "string")
      : undefined,
    custom: body.custom && typeof body.custom === "object" ? (body.custom as ReportRequest["custom"]) : null,
    exportAllRows: true,
    skipAudit: true,
  };
}

function normalizeAuditContext(body: Record<string, unknown> | null, fallbackGeneratedBy: string) {
  const raw = body?.auditContext && typeof body.auditContext === "object" ? (body.auditContext as Record<string, unknown>) : null;
  return {
    generatedBy:
      (typeof raw?.generatedBy === "string" && raw.generatedBy.trim()) ||
      fallbackGeneratedBy,
    timezone: (typeof raw?.timezone === "string" && raw.timezone.trim()) || "UTC",
  };
}

export async function POST(req: Request) {
  try {
    const supabase = await createClient();
    const runtime = await createReportRuntime(supabase);

    if (!canCompany(runtime.ctx, runtime.user.id, "reports.read")) {
      return NextResponse.json({ error: "Sem permissão." }, { status: 403 });
    }

    const body = (await req.json().catch(() => null)) as Record<string, unknown> | null;
    const format = typeof body?.format === "string" ? body.format : "csv";
    const request = normalizeRequest(body ?? {});
    const report = await runReport(runtime, request);
    const auditContext = normalizeAuditContext(
      body,
      String(runtime.user.user_metadata?.name || runtime.user.user_metadata?.full_name || runtime.user.email || runtime.user.id)
    );
    const selectedColumns = report.columns.filter((column) =>
      request.visibleColumnIds?.length ? request.visibleColumnIds.includes(column.id) : true
    );

    await registerReportAuditLog({
      admin: runtime.admin,
      companyId: runtime.ctx.companyId,
      userId: runtime.user.id,
      generatedBy: auditContext.generatedBy,
      timezone: auditContext.timezone,
      eventType: "export",
      format: format === "xlsx" ? "xlsx" : "csv",
      report,
      request,
      visibleColumnIds: request.visibleColumnIds,
      metadata: {
        selected_columns: selectedColumns.map((column) => column.id),
      },
    });

    const arquivo = montarArquivoDoRelatorio({
      report,
      request,
      format: format === "xlsx" ? "xlsx" : "csv",
      generatedBy: auditContext.generatedBy,
      timezone: auditContext.timezone,
    });
    return new NextResponse(arquivo.conteudo as unknown as BodyInit, {
      headers: {
        "Content-Type": arquivo.tipo,
        "Content-Disposition": `attachment; filename="${arquivo.nome}"`,
      },
    });
  } catch (error) {
    return NextResponse.json(
      { error: error instanceof Error ? error.message : "Falha ao exportar relatório." },
      { status: 500 }
    );
  }
}
