// SPEC: PJ2026-0103 HarnessRL draft-2026-06-25-p0-web-caserun-e2e.
// Responsibility: shared CaseRun contracts used by runtime, subject, and closeout modules.

import type { AgentDiffCollectionSummary } from "./hwlab-caserun-diff.ts";
import type { AgentToolCallSummary } from "./hwlab-caserun-evidence.ts";
import type { TraceEventRow } from "./hwlab-cli/trace-renderer.ts";
import type { CaseValidationPlan } from "./hwlab-caserun-validation.ts";

export type EnvLike = Record<string, string | undefined>;
export type ParsedArgs = Record<string, unknown> & { _: string[] };
export type FetchLike = typeof fetch;
export type RunProcessLike = (command: string[], cwd: string, env: Record<string, string | undefined>) => Promise<{ command: string[]; stdout: string; stderr: string; exitCode: number }>;
export type StartProcessLike = (input: { command: string; args: string[]; cwd: string; env: Record<string, string | undefined>; stdoutPath: string; stderrPath: string }) => Promise<{ pid: number }> | { pid: number };

export type CaseContext = {
  parsed: ParsedArgs;
  env: EnvLike;
  fetchImpl: FetchLike;
  cwd: string;
  now: () => string;
  sleep: (ms: number) => Promise<void>;
  runProcess?: RunProcessLike;
  startProcess?: StartProcessLike;
  caseRunTransportFactory?: (context: CaseContext) => Promise<import("../../internal/harnessrl/transport.ts").CaseRunTransport> | import("../../internal/harnessrl/transport.ts").CaseRunTransport;
  argv?: string[];
  rest: string[];
};

export type PreparedCaseRun = {
  caseId: string;
  runId: string;
  runDir: string;
  caseRepo: string;
  caseDir: string;
  caseFile: string;
  sourceSpecPath: string;
  specPath: string;
  apiUrl: string;
  compileOnly: boolean;
  validationPlan?: CaseValidationPlan;
  createdAt: string;
  updatedAt: string;
  definition: Record<string, unknown>;
  subject: PreparedSubjectRun;
  agentTask?: PreparedAgentTask | null;
  agent?: AgentRunStage | null;
  agentTrace?: AgentTraceStage | null;
  agentDiff?: AgentDiffStage | null;
  status?: string;
  stage?: string;
  evidencePath?: string;
  completedAt?: string;
};

export type PreparedSubjectRun = {
  repoLocalPath: string;
  commitId: string;
  subdir: string;
  worktreePath: string;
  workspacePath: string;
  setup: Record<string, unknown>;
  sourceRootBaseline?: SourceRootSnapshot;
  sourceRootAfterPrepare?: SourceRootSnapshot;
};

export type SourceRootSnapshot = {
  label: string;
  statusShort: string;
  diffStat: string;
  diffSha256: string;
  diffBytes: number;
  commands?: Record<string, unknown>;
};

export type PreparedAgentTask = {
  prompt: string;
  workspace: "subjectWorktree";
  constraints: string[];
  providerProfile: string;
  projectId: string;
  timeoutMs?: number;
  pollIntervalMs?: number;
};

export type AgentRunStage = {
  stageStatus: string;
  baseUrl: string;
  projectId: string;
  providerProfile: string;
  conversationId: string;
  sessionId: string;
  threadId: string;
  traceId: string;
  promptPath: string;
  promptSha256: string;
  accepted: Record<string, unknown> | null;
  result: Record<string, unknown> | null;
  terminalStatus?: string;
  commandStatus?: string;
  agentRunStatus?: string;
  requestedProviderProfile?: string;
  resolvedBackendProfile?: string;
  provider?: string;
  model?: string;
  backend?: string;
  infrastructureBackend?: string;
  providerTrace?: Record<string, unknown> | null;
  toolCallSummary?: AgentToolCallSummary | null;
  polls: number;
  timedOut: boolean;
  timeoutMs?: number;
  pollIntervalMs?: number;
  resultUrl?: string;
  lastPollAt?: string;
  lastHttpStatus?: number;
  nextPollCommand?: string;
  traceCommand?: string;
  inspectCommand?: string;
  sessionCommand?: string;
  traceLookup?: Record<string, unknown>;
  sessionResponse: Record<string, unknown> | null;
  error?: Record<string, unknown> | null;
};

export type AgentDiffStage = {
  statusShort: string;
  diffStat: string;
  diffPatchPath: string;
  diffPatchSha256: string;
  diffCollection?: AgentDiffCollectionSummary;
  sourceRootStatusShort: string;
  sourceRootBaseline?: SourceRootSnapshot;
  sourceRootAfterPrepare?: SourceRootSnapshot;
  sourceRootAfterAgent?: SourceRootSnapshot;
  sourceRootChangedAfterPrepare?: boolean;
  sourceRootChangedAfterAgent?: boolean;
  requests: Record<string, unknown>[];
};

export type AgentTraceCommand = {
  source: string;
  seq?: number;
  rowId?: string;
  header?: string;
  toolName?: string;
  status?: string;
  command?: string;
  normalizedCommand?: string;
  bodyPreview?: string;
  exitCode?: number;
};

export type AgentTraceStage = {
  traceId: string;
  status: string;
  httpStatus: number;
  source?: string;
  lookupOnly?: boolean;
  lookup?: Record<string, unknown>;
  sourceEventCount?: number;
  renderedRowCount?: number;
  commandCount: number;
  hwpodCommandCount: number;
  hwpodBuildCommandCount: number;
  keilJobCandidates: string[];
  terminalStatus?: string;
  agentRun?: Record<string, unknown> | null;
  toolCallSummary?: AgentToolCallSummary | null;
  commands: AgentTraceCommand[];
  error?: Record<string, unknown> | null;
};

export type CaseRegistryArchiveFile = {
  path: string;
  bytes: number;
  sha256: string;
  source?: string;
};

export type CaseRegistryArchive = {
  caseRepoRunDir: string;
  artifactManifestPath: string;
  caseRepoFiles: string[];
  files: CaseRegistryArchiveFile[];
  skippedFiles: string[];
  manifest: Record<string, unknown>;
  registrySync?: Record<string, unknown> | null;
};

export type CaseReadableAgentArchive = {
  messagesRel: string;
  traceRel: string;
  transcriptRel: string;
  finalResponseRel: string;
  generatedFiles: string[];
  traceRender: Record<string, unknown>;
  finalResponse: Record<string, unknown>;
};

export type ArchivedAgentTraceSnapshot = {
  traceBody: any;
  rows: TraceEventRow[];
  events: Record<string, unknown>[];
  summary: AgentTraceStage;
};
