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

function isAuditLogRelationUnavailable(error: { code?: string; message?: string; details?: string | null } | null) {
  if (!error) return false;
  return (
    error.code === "42P01" ||
    /report_audit_logs/i.test(String(error.message || "")) ||
    /report_audit_logs/i.test(String(error.details || ""))
  );
}

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: typeof body.page === "number" ? body.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 GET() {
  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 { data, error } = await runtime.admin
      .from("report_audit_logs")
      .select("id,event_type,format,report_key,report_title,total_rows,created_at,metadata")
      .eq("company_id", runtime.ctx.companyId)
      .order("created_at", { ascending: false })
      .limit(50);

    if (error) {
      if (isAuditLogRelationUnavailable(error)) {
        return NextResponse.json({
          logs: [],
          degraded: true,
          warning: "A trilha persistida de auditoria ainda nao esta disponivel neste ambiente.",
        });
      }
      return NextResponse.json({ error: "Falha ao listar auditoria." }, { status: 500 });
    }

    return NextResponse.json({ logs: data ?? [] });
  } catch (error) {
    return NextResponse.json(
      { error: error instanceof Error ? error.message : "Falha ao listar auditoria de relatórios." },
      { status: 500 }
    );
  }
}

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" && isExportFormat(body.format) ? body.format : null;
    if (!format || (format !== "pdf" && format !== "print")) {
      return NextResponse.json({ error: "Formato de auditoria inválido." }, { status: 400 });
    }

    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)
    );

    await registerReportAuditLog({
      admin: runtime.admin,
      companyId: runtime.ctx.companyId,
      userId: runtime.user.id,
      generatedBy: auditContext.generatedBy,
      timezone: auditContext.timezone,
      eventType: "export",
      format,
      report,
      request,
      visibleColumnIds: request.visibleColumnIds,
    });

    return NextResponse.json({ ok: true });
  } catch (error) {
    return NextResponse.json(
      { error: error instanceof Error ? error.message : "Falha ao registrar auditoria do relatório." },
      { status: 500 }
    );
  }
}
