type WorkbookCellValue = boolean | Date | number | string | null | undefined;

export type ResourceMonthReportExplainability = {
  entity: "resource_month";
  periodMonth: string | null;
  locationContextColumns: string[];
  holidayMetricColumns: string[];
  absenceMetricColumns: string[];
  capacityMetricColumns: string[];
  chargeabilityMetricColumns: string[];
  missingRecommendedColumns: string[];
  notes: string[];
};

export type ReportExplainability = ResourceMonthReportExplainability;

export type ReportExportSheet = {
  name: string;
  rows: WorkbookCellValue[][];
};

type BuildReportWorkbookSheetsInput = {
  columns: string[];
  rows: Record<string, unknown>[];
  groups: Array<{ key: string; label: string; rowCount: number; startIndex: number }>;
  groupBy?: string;
  explainability?: ReportExplainability;
  resolveColumnLabel: (column: string) => string;
};

export function buildResourceMonthExplainabilitySheetRows(
  explainability: ReportExplainability,
  resolveColumnLabel: (column: string) => string,
): WorkbookCellValue[][] {
  const mapLabels = (columns: string[]) => (
    columns.length > 0 ? columns.map(resolveColumnLabel) : ["none"]
  );

  return [
    ["Resource Month Explainability"],
    ["Period Month", explainability.periodMonth ?? "current month"],
    ["Location Context Columns", ...mapLabels(explainability.locationContextColumns)],
    ["Holiday Metric Columns", ...mapLabels(explainability.holidayMetricColumns)],
    ["Absence Metric Columns", ...mapLabels(explainability.absenceMetricColumns)],
    ["Capacity Metric Columns", ...mapLabels(explainability.capacityMetricColumns)],
    ["Chargeability Metric Columns", ...mapLabels(explainability.chargeabilityMetricColumns)],
    ["Missing Recommended Columns", ...mapLabels(explainability.missingRecommendedColumns)],
    [],
    ["Notes"],
    ...explainability.notes.map((note) => [note]),
  ];
}

export function buildReportWorkbookSheets(
  input: BuildReportWorkbookSheetsInput,
): ReportExportSheet[] {
  const headerRow = input.columns.map(input.resolveColumnLabel);
  const groupStartByIndex = new Map(
    input.groups.map((group) => [group.startIndex, group] as const),
  );
  const groupByLabel = input.groupBy ? input.resolveColumnLabel(input.groupBy) : null;

  const reportRows: WorkbookCellValue[][] = [headerRow];
  input.rows.forEach((row, index) => {
    const group = groupStartByIndex.get(index);
    if (group && groupByLabel) {
      reportRows.push([
        `${groupByLabel}: ${group.label} (${group.rowCount})`,
        ...Array.from({ length: Math.max(0, input.columns.length - 1) }, () => ""),
      ]);
    }

    reportRows.push(input.columns.map((column) => {
      const value = row[column];
      if (value === undefined) {
        return "";
      }
      return value as WorkbookCellValue;
    }));
  });

  const sheets: ReportExportSheet[] = [{ name: "Report", rows: reportRows }];
  if (input.explainability?.entity === "resource_month") {
    sheets.push({
      name: "Explainability",
      rows: buildResourceMonthExplainabilitySheetRows(input.explainability, input.resolveColumnLabel),
    });
  }

  return sheets;
}
