import type { Prisma } from "@capakraken/db";
import { DispoImportSourceKind, StagedRecordStatus } from "@capakraken/db";
import { parseDispoChargeabilityWorkbook } from "./parse-chargeability-workbook.js";
import { ensureImportBatch, finalizeImportBatchStage, getWorkbookFileName, type DispoChargeabilityImportInput, type DispoImportDbClient } from "./shared.js";

export interface StageDispoChargeabilityResourcesResult {
  batchId: string;
  counts: {
    stagedResources: number;
    unresolved: number;
    warnings: number;
  };
}

export async function stageDispoChargeabilityResources(
  db: DispoImportDbClient,
  input: DispoChargeabilityImportInput,
): Promise<StageDispoChargeabilityResourcesResult> {
  const batchInput: {
    chargeabilitySourceFile: string;
    importBatchId?: string;
    notes?: string | null;
  } = {
    chargeabilitySourceFile: getWorkbookFileName(input.chargeabilityWorkbookPath),
  };

  if (input.importBatchId !== undefined) {
    batchInput.importBatchId = input.importBatchId;
  }
  if (input.notes !== undefined) {
    batchInput.notes = input.notes;
  }

  const batch = await ensureImportBatch(db, batchInput);
  const parsed = await parseDispoChargeabilityWorkbook(input.chargeabilityWorkbookPath);
  const excludedIds = new Set(input.excludedResourceExternalIds ?? []);
  const filteredResources = parsed.resources.filter(
    (resource) => !excludedIds.has(resource.canonicalExternalId),
  );
  const filteredUnresolved = parsed.unresolved.filter(
    (record) => !record.resourceExternalId || !excludedIds.has(record.resourceExternalId),
  );
  const sourceWorkbook = getWorkbookFileName(input.chargeabilityWorkbookPath);

  await db.stagedResource.deleteMany({
    where: {
      importBatchId: batch.id,
      sourceKind: DispoImportSourceKind.CHARGEABILITY,
    },
  });

  if (filteredResources.length > 0) {
    await db.stagedResource.createMany({
      data: filteredResources.map((resource) => ({
        importBatchId: batch.id,
        status: resource.warnings.length > 0
          ? StagedRecordStatus.PARSED
          : StagedRecordStatus.NORMALIZED,
        sourceKind: DispoImportSourceKind.CHARGEABILITY,
        sourceWorkbook,
        sourceSheet: "ChgFC",
        sourceRow: resource.sourceRow,
        canonicalExternalId: resource.canonicalExternalId,
        enterpriseId: resource.enterpriseId,
        eid: resource.eid,
        displayName: resource.displayName,
        email: resource.email,
        chapter: resource.chapter,
        chapterCode: resource.chapterCode,
        managementLevelGroupName: resource.managementLevelGroupName,
        managementLevelName: resource.managementLevelName,
        countryCode: resource.countryCode,
        metroCityName: resource.metroCityName,
        clientUnitName: resource.clientUnitName,
        resourceType: resource.resourceType,
        chargeabilityTarget: resource.chargeabilityTarget,
        fte: resource.fte,
        availability: resource.availability,
        roleTokens: resource.roleTokens,
        warnings: resource.warnings,
        rawPayload: {
          rawResourceType: resource.rawResourceType,
        } as Prisma.InputJsonValue,
        normalizedData: {
          chapter: resource.chapter,
          chapterCode: resource.chapterCode,
          chargeabilityTarget: resource.chargeabilityTarget,
          clientUnitName: resource.clientUnitName,
          countryCode: resource.countryCode,
          fte: resource.fte,
          managementLevelGroupName: resource.managementLevelGroupName,
          metroCityName: resource.metroCityName,
          roleTokens: resource.roleTokens,
        } as Prisma.InputJsonValue,
      })),
    });
  }

  await db.stagedUnresolvedRecord.deleteMany({
    where: {
      importBatchId: batch.id,
      sourceKind: DispoImportSourceKind.CHARGEABILITY,
    },
  });

  if (filteredUnresolved.length > 0) {
    await db.stagedUnresolvedRecord.createMany({
      data: filteredUnresolved.map((record) => ({
        importBatchId: batch.id,
        status: StagedRecordStatus.UNRESOLVED,
        sourceKind: DispoImportSourceKind.CHARGEABILITY,
        sourceWorkbook,
        sourceSheet: "ChgFC",
        sourceRow: record.sourceRow,
        sourceColumn: record.sourceColumn ?? null,
        recordType: record.recordType,
        resourceExternalId: record.resourceExternalId ?? null,
        projectKey: record.projectKey ?? null,
        message: record.message,
        resolutionHint: record.resolutionHint ?? null,
        warnings: record.warnings,
        rawPayload: {} as Prisma.InputJsonValue,
        normalizedData: record.normalizedData as Prisma.InputJsonValue,
      })),
    });
  }

  const warningCount =
    parsed.warnings.length +
    filteredResources.reduce((count, resource) => count + resource.warnings.length, 0);
  const summary = {
    stagedResources: filteredResources.length,
    unresolved: filteredUnresolved.length,
    warnings: warningCount,
  };

  await finalizeImportBatchStage(db, {
    batchId: batch.id,
    existingSummary: batch.summary,
    key: "chargeability",
    summary,
  });

  return {
    batchId: batch.id,
    counts: summary,
  };
}
