import {
  assessDispoImportReadiness,
  persistDispoImportReadiness,
  type DispoImportReadinessReport,
} from "./assess-import-readiness.js";
import { type DispoImportDbClient } from "./shared.js";
import { stageDispoChargeabilityResources } from "./stage-chargeability-resources.js";
import { stageDispoPlanningData } from "./stage-dispo-planning.js";
import { stageDispoProjects } from "./stage-dispo-projects.js";
import { stageDispoRosterResources } from "./stage-dispo-roster-resources.js";
import { stageDispoReferenceData } from "./stage-reference-data.js";

export interface StageDispoImportBatchInput {
  chargeabilityWorkbookPath: string;
  costWorkbookPath?: string;
  notes?: string | null;
  planningWorkbookPath: string;
  referenceWorkbookPath: string;
  rosterWorkbookPath?: string;
}

export interface StageDispoImportBatchResult {
  batchId: string;
  counts: {
    stagedAssignments: number;
    stagedAvailabilityRules: number;
    stagedClients: number;
    stagedProjects: number;
    stagedResources: number;
    stagedRosterResources: number;
    stagedVacations: number;
    unresolved: number;
  };
  readiness: DispoImportReadinessReport;
}

export async function stageDispoImportBatch(
  db: DispoImportDbClient,
  input: StageDispoImportBatchInput,
): Promise<StageDispoImportBatchResult> {
  const referenceResult = await stageDispoReferenceData(db, {
    referenceWorkbookPath: input.referenceWorkbookPath,
    ...(input.notes !== undefined ? { notes: input.notes } : {}),
  });

  const batchId = referenceResult.batchId;

  const rosterResult = input.rosterWorkbookPath
    ? await stageDispoRosterResources(db, {
      importBatchId: batchId,
      rosterWorkbookPath: input.rosterWorkbookPath,
      ...(input.costWorkbookPath ? { costWorkbookPath: input.costWorkbookPath } : {}),
      ...(input.notes !== undefined ? { notes: input.notes } : {}),
    })
    : { counts: { stagedResources: 0, unresolved: 0, warnings: 0, ignoredPseudoDemandRows: 0, excludedResources: 0 }, excludedCanonicalExternalIds: [] };

  const chargeabilityResult = await stageDispoChargeabilityResources(db, {
    importBatchId: batchId,
    chargeabilityWorkbookPath: input.chargeabilityWorkbookPath,
    excludedResourceExternalIds: rosterResult.excludedCanonicalExternalIds,
    ...(input.notes !== undefined ? { notes: input.notes } : {}),
  });

  const planningResult = await stageDispoPlanningData(db, {
    importBatchId: batchId,
    planningWorkbookPath: input.planningWorkbookPath,
    excludedResourceExternalIds: rosterResult.excludedCanonicalExternalIds,
    ...(input.notes !== undefined ? { notes: input.notes } : {}),
  });

  const projectResult = await stageDispoProjects(db, {
    importBatchId: batchId,
    planningWorkbookPath: input.planningWorkbookPath,
    excludedResourceExternalIds: rosterResult.excludedCanonicalExternalIds,
    ...(input.notes !== undefined ? { notes: input.notes } : {}),
  });

  const readiness = await persistDispoImportReadiness(db, {
    importBatchId: batchId,
    referenceWorkbookPath: input.referenceWorkbookPath,
    chargeabilityWorkbookPath: input.chargeabilityWorkbookPath,
    planningWorkbookPath: input.planningWorkbookPath,
    ...(input.costWorkbookPath ? { costWorkbookPath: input.costWorkbookPath } : {}),
    ...(input.rosterWorkbookPath ? { rosterWorkbookPath: input.rosterWorkbookPath } : {}),
    ...(input.notes !== undefined ? { notes: input.notes } : {}),
  });

  return {
    batchId,
    counts: {
      stagedClients: referenceResult.counts.stagedClients,
      stagedResources:
        chargeabilityResult.counts.stagedResources + (rosterResult?.counts.stagedResources ?? 0),
      stagedRosterResources: rosterResult?.counts.stagedResources ?? 0,
      stagedProjects: projectResult.counts.stagedProjects,
      stagedAssignments: planningResult.counts.stagedAssignments,
      stagedVacations: planningResult.counts.stagedVacations,
      stagedAvailabilityRules: planningResult.counts.stagedAvailabilityRules,
      unresolved:
        chargeabilityResult.counts.unresolved +
        planningResult.counts.unresolved +
        (rosterResult?.counts.unresolved ?? 0),
    },
    readiness,
  };
}
