import type { HistoryReportSection, ObservabilityReport, ObservabilityReportQuery, ReportCoverageStatus } from "@overdeck/report-contract";
import { buildActivityObservabilityReport, type ActivityReportDependencies } from "./activity-report";
import { buildExecutionReportSection, type ExecutionReportInput } from "./execution-report";
import { buildReliabilityReportSection, type ReliabilityReportInput } from "./reliability-report";
import { buildCapacityReportSection, type CapacityReportInput } from "./capacity-report";
import { buildLineageReportSection } from "./lineage-report";

export interface ObservabilityReportDependencies {
  activity?: ActivityReportDependencies;
  execution: ExecutionReportInput;
  reliability?: ReliabilityReportInput;
  capacity?: CapacityReportInput;
}

function coverageRank(status: ReportCoverageStatus): number {
  return status === "unavailable" ? 3 : status === "partial" ? 2 : status === "stale" ? 1 : 0;
}

function worstCoverage(values: ReportCoverageStatus[]): ReportCoverageStatus {
  return values.reduce<ReportCoverageStatus>((worst, value) => coverageRank(value) > coverageRank(worst) ? value : worst, "complete");
}

export function appendHistoryReportSection(
  report: ObservabilityReport,
  history: HistoryReportSection,
): ObservabilityReport {
  return {
    ...report,
    coverage: {
      ...report.coverage,
      status: worstCoverage([report.coverage.status, history.status]),
      gaps: [...report.coverage.gaps, ...history.gaps],
    },
    sections: [...report.sections, history],
  };
}

export function buildObservabilityReport(
  query: ObservabilityReportQuery,
  dependencies: ObservabilityReportDependencies,
): ObservabilityReport {
  const activity = buildActivityObservabilityReport(query, dependencies.activity);
  const execution = buildExecutionReportSection(query, dependencies.execution);
  const lineage = buildLineageReportSection({
    execution,
    ...(dependencies.execution.requestStories !== undefined
      ? { requestStories: dependencies.execution.requestStories }
      : {}),
  });
  const reliability = dependencies.reliability
    ? buildReliabilityReportSection(query, dependencies.reliability)
    : undefined;
  const capacity = dependencies.capacity
    ? buildCapacityReportSection(query, dependencies.capacity)
    : undefined;
  return {
    ...activity,
    coverage: {
      ...activity.coverage,
      status: worstCoverage([
        activity.coverage.status,
        execution.status,
        lineage.status,
        ...(reliability ? [reliability.status] : []),
        ...(capacity ? [capacity.status] : []),
      ]),
      gaps: [
        ...activity.coverage.gaps,
        ...execution.gaps,
        ...lineage.gaps,
        ...(reliability?.gaps ?? []),
        ...(capacity?.gaps ?? []),
      ],
    },
    sections: [
      ...activity.sections,
      execution,
      lineage,
      ...(reliability ? [reliability] : []),
      ...(capacity ? [capacity] : []),
    ],
  };
}
