import type { SupabaseClient } from "@supabase/supabase-js";
import type {
  ReportAuditEventType,
  ReportAuditFormat,
  ReportExportFormat,
  ReportRequest,
  ReportResponse,
  ReportSort,
} from "@/lib/reports/contracts";
import { formatValueByType } from "@/lib/reports/utils";

export const REPORT_RULE_VERSION = "Especificacao Funcional Oficial / REL-021 / 2026-08-18";

export type ReportAuditMeta = {
  generatedBy: string;
  generatedAt: string;
  timezone: string;
  sortLabel: string;
  totalRows: number;
  ruleVersion: string;
  filterSummary: string[];
};

const FILTER_LABELS: Record<string, string> = {
  startDate: "Data inicial",
  endDate: "Data final",
  client: "Cliente",
  paymentMethod: "Forma de pagamento",
  status: "Status",
  bankAccount: "Conta bancária",
  financialCategory: "Categoria financeira",
  channel: "Canal",
  seller: "Vendedor",
  category: "Categoria",
  supplier: "Fornecedor",
  city: "Cidade",
  state: "Estado",
  universe: "Universo",
  groupBy: "Agrupar por",
  sortBy: "Ordenação",
};

export function buildAppliedFiltersSummary(report: ReportResponse) {
  return Object.entries(report.appliedFilters)
    .flatMap(([key, value]) => {
      if (value === null) return [];
      if (Array.isArray(value) && value.length === 0) return [];
      if (typeof value === "string" && value.trim() === "") return [];
      const text = Array.isArray(value) ? value.join(", ") : String(value);
      return [`${FILTER_LABELS[key] || key}: ${text}`];
    });
}

export function getReportSortSummary(sort: ReportSort, report: ReportResponse) {
  if (!sort) return "Sem ordenacao explicita";
  const column = report.columns.find((item) => item.id === sort.columnId);
  const direction = sort.direction === "asc" ? "crescente" : "decrescente";
  return `${column?.label || sort.columnId} (${direction})`;
}

export function buildReportAuditMeta(params: {
  report: ReportResponse;
  generatedBy: string;
  sort: ReportSort;
  timezone?: string | null;
}) {
  const { report, generatedBy, sort, timezone } = params;
  return {
    generatedBy,
    generatedAt: new Date(report.generatedAt).toLocaleString("pt-BR"),
    timezone: String(timezone || "UTC"),
    sortLabel: getReportSortSummary(sort, report),
    totalRows: report.totalRows,
    ruleVersion: REPORT_RULE_VERSION,
    filterSummary: buildAppliedFiltersSummary(report),
  } satisfies ReportAuditMeta;
}

export function buildReportExportMetadataRows(report: ReportResponse, audit: ReportAuditMeta) {
  return [
    ["Sistema", "Ktalogu ERP"],
    ["Relatorio", report.title],
    ["Empresa", report.company.companyName],
    ["Documento da empresa", report.company.companyDocument || "—"],
    ["Periodo", `${String(report.appliedFilters.startDate || "—")} ate ${String(report.appliedFilters.endDate || "—")}`],
    ["Data e hora de geracao", audit.generatedAt],
    ["Usuario gerador", audit.generatedBy],
    ["Timezone", audit.timezone],
    ["Criterio de ordenacao", audit.sortLabel],
    ["Versao da regra", audit.ruleVersion],
    ["Total de registros exportados", String(audit.totalRows)],
    ["Filtros aplicados", audit.filterSummary.length > 0 ? audit.filterSummary.join(" • ") : "Sem filtros complementares aplicados."],
  ];
}

export function buildReportCsvExport(params: {
  report: ReportResponse;
  audit: ReportAuditMeta;
  visibleColumnIds?: string[];
}) {
  const { report, audit, visibleColumnIds } = params;
  const selectedColumns = report.columns.filter((column) =>
    visibleColumnIds?.length ? visibleColumnIds.includes(column.id) : true
  );
  /* Texto que começa com = + - @ (ou tab/CR) vira fórmula no Excel: um nome
     de cliente "=HYPERLINK(...)" executaria ao abrir a planilha. O apóstrofo
     na frente faz o Excel ler como texto (mesma régua de celulaCsv, em
     lib/assistentes/ferramentas/operacao-regras.ts). Número negativo não é
     texto e fica como está. */
  const celula = (texto: string, bruto: unknown = texto) => {
    const seguro = typeof bruto === "string" && /^[=+\-@\t\r]/.test(texto) ? `'${texto}` : texto;
    return `"${seguro.replaceAll('"', '""')}"`;
  };
  const metadataLines = buildReportExportMetadataRows(report, audit).map(
    ([label, value]) => `"# ${label}";${celula(String(value), value)}`
  );
  const headerLine = selectedColumns.map((column) => celula(String(column.label))).join(";");
  const bodyLines = report.rows.map((row) =>
    selectedColumns
      .map((column) => {
        const bruto = row[column.id] ?? null;
        return celula(String(formatValueByType(bruto, column.type)), bruto);
      })
      .join(";")
  );

  return [...metadataLines, "", headerLine, ...bodyLines].join("\n");
}

export async function registerReportAuditLog(params: {
  admin: SupabaseClient;
  companyId: string;
  userId: string;
  generatedBy: string;
  timezone?: string | null;
  eventType: ReportAuditEventType;
  format: ReportAuditFormat;
  report: ReportResponse;
  request: ReportRequest;
  visibleColumnIds?: string[];
  metadata?: Record<string, unknown>;
}) {
  const {
    admin,
    companyId,
    userId,
    generatedBy,
    timezone,
    eventType,
    format,
    report,
    request,
    visibleColumnIds,
    metadata,
  } = params;

  const audit = buildReportAuditMeta({
    report,
    generatedBy,
    sort: request.sort,
    timezone,
  });

  const { error } = await admin.from("report_audit_logs").insert({
    company_id: companyId,
    user_id: userId,
    event_type: eventType,
    format,
    report_key: request.tab,
    report_title: report.title,
    applied_filters: report.appliedFilters,
    sort_config: request.sort,
    visible_column_ids: visibleColumnIds && visibleColumnIds.length > 0 ? visibleColumnIds : null,
    total_rows: report.totalRows,
    export_all_rows: request.exportAllRows === true,
    metadata: {
      ...metadata,
      generated_by: generatedBy,
      generated_at: report.generatedAt,
      timezone: audit.timezone,
      sort_label: audit.sortLabel,
      rule_version: audit.ruleVersion,
      filter_summary: audit.filterSummary,
    },
  });

  if (error) {
    console.error("[reports:audit]", error.message);
  }
}

export function isExportFormat(value: string): value is ReportExportFormat {
  return value === "csv" || value === "xlsx" || value === "pdf" || value === "print";
}
