import type { CompletionRung } from "./types.js";
import type { AsyncCoverageRow, CoverageRowValidation } from "./types.js";

const SYNC_MAX_RUNG: CompletionRung = "response-accepted";

export function buildSyncCoverageRow(
  branchId: string,
  provenRung: CompletionRung | undefined,
): AsyncCoverageRow {
  return {
    branchId,
    coverageKind: "sync-route",
    provenRung,
    claimsDownstreamAsync: false,
  };
}

export function buildAsyncCoverageRow(
  branchId: string,
  provenRung: CompletionRung | undefined,
): AsyncCoverageRow {
  return {
    branchId,
    coverageKind: "async-branch",
    provenRung,
  };
}

export function validateCoverageRows(rows: readonly AsyncCoverageRow[]): CoverageRowValidation {
  const violations: CoverageRowValidation["violations"] = [];
  const seenBranchIds = new Set<string>();

  for (const row of rows) {
    if (seenBranchIds.has(row.branchId)) {
      violations.push({
        branchId: row.branchId,
        fact: `Coverage rows must stay distinct per branch; duplicate row for ${row.branchId}`,
      });
      continue;
    }
    seenBranchIds.add(row.branchId);

    if (row.coverageKind === "sync-route") {
      if (row.claimsDownstreamAsync === true) {
        violations.push({
          branchId: row.branchId,
          fact: "Synchronous route coverage cannot claim downstream async branch",
        });
      }
      if (
        row.provenRung !== undefined &&
        row.provenRung !== SYNC_MAX_RUNG
      ) {
        violations.push({
          branchId: row.branchId,
          fact: `Synchronous route coverage cannot claim async rung ${row.provenRung}`,
        });
      }
    }
  }

  return {
    valid: violations.length === 0,
    violations,
  };
}
