import type {
  CoverageOutcomeRecord,
  CoverageReason,
  HarnessOutcomeRecord,
  OutcomeWitnessView,
} from "./types.js";

const COVERAGE_REMEDIATION: Record<CoverageReason, string> = {
  "empty-selection":
    "Expand the requested selection or define an explicit expected-empty contract for this scope.",
  "unproven-precondition":
    "Restore or prove the required precondition witness before rerunning this scope.",
  "inert-perturbation":
    "Adjust the perturbation so it reaches the intended targets, then rerun the scope.",
  "failed-known-bad":
    "Repair the known-bad calibration fixture so it fails as expected, then rerun calibration.",
  "unsupported-capability":
    "Enable the requested capability profile or narrow scope to a supported profile.",
  "unreachable-target":
    "Restore target reachability for the planned execution context, then rerun the scope.",
  "missing-artifact":
    "Restore the missing artifact referenced by this coverage outcome, then rerun the scope.",
};

const WITNESS_KIND_BY_REASON: Partial<Record<CoverageReason, string>> = {
  "unproven-precondition": "precondition",
  "failed-known-bad": "calibration",
  "inert-perturbation": "perturbation",
};

export function coverageRemediation(reason: CoverageReason): string {
  return COVERAGE_REMEDIATION[reason];
}

export function harnessRemediation(outcome: HarnessOutcomeRecord): string {
  const rerunScope = outcome.scope.id;
  const retryHint = outcome.cause.retryable
    ? "This failure is retryable after correcting the harness."
    : "This failure requires a harness fix before rerun.";
  return [
    `Correct the harness failure in phase "${outcome.phase}" (${outcome.cause.code}: ${outcome.cause.message}).`,
    `Rerun a successful comparable scope for "${rerunScope}".`,
    retryHint,
  ].join(" ");
}

export function coverageWitnesses(outcome: CoverageOutcomeRecord): OutcomeWitnessView[] {
  const defaultKind = WITNESS_KIND_BY_REASON[outcome.reason] ?? "witness";
  return outcome.witnessRefs.map((witness) => {
    const view: OutcomeWitnessView = {
      id: witness.id,
      kind: defaultKind,
      description: witness.artifactRef === undefined
        ? `Witness reference ${witness.id}`
        : `Witness artifact ${witness.artifactRef.relativePath}`,
    };
    if (witness.artifactRef !== undefined) {
      view.artifactPath = witness.artifactRef.relativePath;
    }
    if (outcome.reason === "unproven-precondition") {
      view.status = "failed";
    }
    return view;
  });
}

export type InteractionObligationView = {
  id: string;
  witnessIds: string[];
  unproven?: string;
  details: Array<{ label: string; value: string }>;
};

const PRECONDITION_DETAIL_LABELS: Record<string, string> = {
  expected: "Expected",
  observed: "Observed",
  setup: "Setup",
  locator: "Locator",
  failedPrecondition: "Failed precondition",
};

function detailValue(value: unknown): string {
  return typeof value === "string" ? value : JSON.stringify(value);
}

export function interactionObligations(
  outcome: CoverageOutcomeRecord,
): InteractionObligationView[] {
  const interaction = outcome.interaction;
  if (interaction === undefined) return [];
  return interaction.evidence.obligations.map((obligation) => {
    const view: InteractionObligationView = {
      id: obligation.id,
      witnessIds: obligation.witnessRefs.map((witness) => witness.id),
      details: [],
    };
    if (!("unproven" in obligation)) return view;
    const evidence: Record<string, unknown> = obligation.unproven;
    view.unproven = obligation.unproven.unproven;
    for (const [key, label] of Object.entries(PRECONDITION_DETAIL_LABELS)) {
      const value = evidence[key];
      if (value !== undefined) view.details.push({ label, value: detailValue(value) });
    }
    const witness = evidence.witness as { id: string } | undefined;
    if (witness !== undefined) view.details.push({ label: "Witness", value: witness.id });
    const artifact = evidence.artifact as { relativePath: string } | undefined;
    if (artifact !== undefined) {
      view.details.push({ label: "Artifact", value: artifact.relativePath });
    }
    return view;
  });
}

export function formatExecutionContext(
  context: CoverageOutcomeRecord["context"] | HarnessOutcomeRecord["plannedContext"],
): { kind: string; details: Array<{ label: string; value: string }> } {
  if (context === undefined) {
    return { kind: "unknown", details: [] };
  }

  if (context.kind === "browser") {
    return {
      kind: "browser",
      details: [{ label: "Cell", value: context.cell.id }],
    };
  }

  const details: Array<{ label: string; value: string }> = [
    { label: "Surface", value: context.surfaceId },
    { label: "Adapter", value: context.adapterId },
    { label: "Seed", value: context.seed },
  ];
  if (context.action !== undefined) {
    details.push({ label: "Action", value: context.action.id });
  }
  if (Object.keys(context.environment).length > 0) {
    details.push({ label: "Environment", value: JSON.stringify(context.environment) });
  }
  return { kind: context.kind, details };
}
