import type {
  AgentRunId,
  AttemptId,
  ChangeSetId,
  FactoryRunId,
  PlanRevisionId,
  PrincipalId,
  ProjectId,
  ProviderId,
  ReviewId,
  TaskId,
  WorkspaceId,
} from "./ids.js";
import type { ProviderReference } from "./providers.js";

export type I1TaskStatus =
  | "planned"
  | "ready"
  | "dispatched"
  | "queued"
  | "executing"
  | "waiting"
  | "blocked"
  | "review"
  | "correction"
  | "completed"
  | "cancelled"
  | "failed";

export type I1FactoryRunStatus =
  | "planned"
  | "queued"
  | "starting"
  | "running"
  | "waiting"
  | "blocked"
  | "cancelling"
  | "cancelled"
  | "failed"
  | "retryable"
  | "resolving"
  | "completed";

export type I1AgentRunStatus =
  "planned" | "queued" | "active" | "waiting" | "completed" | "cancelled" | "failed";

export type I1AttemptStatus = "created" | "provisioning" | "running" | "checkpointing" | "terminal";

export type I1AttemptSelectionKind = "initial" | "retry" | "fallback";

export type I1AttentionKind =
  "none" | "transient-recovery" | "capacity" | "authorization" | "decision" | "policy" | "failure";

export interface I1AttentionReason {
  readonly kind: I1AttentionKind;
  readonly code: string;
  readonly summary: string;
  readonly humanActionRequired: boolean;
}

export type I1WaitKind =
  "capacity" | "provider" | "authorization" | "decision" | "dependency" | "policy" | "unknown";

export interface I1WaitReason {
  readonly kind: I1WaitKind;
  readonly code: string;
  readonly summary: string;
  readonly since: string;
  readonly nextCheckAt?: string;
}

export type I1NextActionKind = "automatic" | "user" | "protected" | "none";

export interface I1NextAction {
  readonly kind: I1NextActionKind;
  readonly code: string;
  readonly summary: string;
}

export type I1RetryDisposition =
  "not-applicable" | "automatic" | "manual" | "blocked" | "terminal" | "unknown";

export interface I1FailureDetail {
  readonly failureClass: string;
  readonly cause: string;
  readonly retryDisposition: I1RetryDisposition;
  readonly exactSourceIdentity?: string;
  readonly candidateDigest?: string;
  readonly occurredAt?: string;
  readonly partial: boolean;
}

export type I1WipSafetyState = "safe" | "unsafe" | "unknown";

export interface I1WipSafety {
  readonly state: I1WipSafetyState;
  readonly workspaceId?: WorkspaceId;
  readonly checkpointIdentity?: string;
  readonly checkpointedAt?: string;
  readonly preservedFileCount?: number;
  readonly cleanupAllowed: boolean;
  readonly reason: string;
}

export interface I1WorkProjection {
  readonly taskId: TaskId;
  readonly planRevisionId: PlanRevisionId;
  readonly title: string;
  readonly status: I1TaskStatus;
  readonly currentActorId?: PrincipalId;
  readonly currentAgentRunId?: AgentRunId;
  readonly stage: string;
  readonly lastProgressAt?: string;
  readonly deadlineAt?: string;
  readonly wait?: I1WaitReason;
  readonly attention: I1AttentionReason;
  readonly nextAction: I1NextAction;
}

export interface I1AttemptDetail {
  readonly id: AttemptId;
  readonly workspaceId: WorkspaceId;
  readonly status: I1AttemptStatus;
  readonly providerId?: ProviderId;
  readonly accountId?: string;
  readonly model?: string;
  readonly selection: {
    readonly kind: I1AttemptSelectionKind;
    readonly reason: string;
    readonly previousAttemptId?: AttemptId;
  };
  readonly providerReference?: ProviderReference;
  readonly reason?: string;
  readonly toolCalls?: readonly { readonly name: string; readonly summary: string }[];
}

export interface I1AgentRunDetail {
  readonly id: AgentRunId;
  readonly taskId: TaskId;
  readonly role: "coder" | "reviewer";
  readonly status: I1AgentRunStatus;
  readonly reason?: string;
  readonly currentAttemptId?: AttemptId;
  readonly attempts: readonly I1AttemptDetail[];
}

export interface I1ContinuationIdentity {
  readonly factoryRunId: FactoryRunId;
  readonly reattachable: boolean;
  readonly continuationKey: string;
  readonly reason?: string;
}

export interface I1FactoryRunDetailReadModel {
  readonly id: FactoryRunId;
  readonly revision: number;
  readonly projectId: ProjectId;
  readonly planRevisionId: PlanRevisionId;
  readonly status: I1FactoryRunStatus;
  readonly reason?: string;
  readonly stage: string;
  readonly lastProgressAt?: string;
  readonly deadlineAt?: string;
  readonly work: readonly I1WorkProjection[];
  readonly agentRuns: readonly I1AgentRunDetail[];
  readonly wait?: I1WaitReason;
  readonly failure?: I1FailureDetail;
  readonly retryDisposition: I1RetryDisposition;
  readonly wip: I1WipSafety;
  readonly liveExecutorPresent: boolean;
  readonly historicalAvailable: boolean;
  readonly continuation: I1ContinuationIdentity;
}

export type I1ChangeSetStatus =
  | "collecting"
  | "candidate-ready"
  | "publishing"
  | "published"
  | "reviewing"
  | "verifying"
  | "ready-to-merge"
  | "merged"
  | "changes-requested"
  | "publication-failed"
  | "superseded"
  | "cancelled";

export type I1ReviewStatus = "requested" | "reviewing" | "submitted";
export type I1ReviewDisposition = "approved" | "changes-requested" | "blocked" | "superseded";

export interface I1ReviewDetail {
  readonly id: ReviewId;
  readonly reviewerPrincipalId: PrincipalId;
  readonly reviewerAgentRunId?: AgentRunId;
  readonly status: I1ReviewStatus;
  readonly disposition?: I1ReviewDisposition;
}

export type I1FindingSeverity = "blocking" | "warning" | "recommendation" | "info";
export interface I1ReviewFinding {
  readonly id: string;
  readonly severity: I1FindingSeverity;
  readonly summary: string;
  readonly source?: string;
  readonly resolved: boolean;
}

export type I1EvidenceState = "passed" | "failed" | "stale" | "missing";
export interface I1VerificationEvidence {
  readonly id: string;
  readonly name: string;
  readonly state: I1EvidenceState;
  readonly source: string;
  readonly observedAt: string;
  readonly candidateDigest: string;
  readonly required?: boolean;
  readonly reference?:
    | { readonly kind: "provider-observation"; readonly providerReference: ProviderReference }
    | {
        readonly kind: "workspace-checkpoint";
        readonly workspaceId: WorkspaceId;
        readonly checkpointDigest: string;
        readonly observedAt: string;
      };
  readonly details?: Readonly<Record<string, unknown>>;
}

export interface I1RepositoryRevisionIdentity {
  readonly reference: string;
  readonly revision: string;
}

export interface I1MergeGateCondition {
  readonly code: string;
  readonly satisfied: boolean;
  readonly summary: string;
}

export interface I1ProtectedActionAvailability {
  readonly available: boolean;
  readonly reasonCode:
    | "ready"
    | "candidate-state"
    | "review"
    | "evidence"
    | "provider-checks"
    | "publication"
    | "policy"
    | "authority"
    | "target-revision"
    | "terminal";
  readonly summary: string;
}

export interface I1MergedResultIdentity {
  readonly target: I1RepositoryRevisionIdentity;
  readonly providerReference?: ProviderReference;
  readonly mergedAt: string;
  readonly mergedBy?: PrincipalId;
}

export interface I1ChangeSetReviewReadModel {
  readonly id: ChangeSetId;
  readonly revision: number;
  readonly projectId: ProjectId;
  readonly taskId: TaskId;
  readonly status: I1ChangeSetStatus;
  readonly baseIdentity: string;
  readonly candidateDigest: string;
  readonly candidate: {
    readonly treeDigest: string;
    readonly patchDigest: string;
    readonly changedPaths: readonly string[];
    readonly changes: readonly {
      readonly path: string;
      readonly kind: "add" | "modify" | "delete";
    }[];
  };
  readonly reviews: readonly I1ReviewDetail[];
  readonly findings: readonly I1ReviewFinding[];
  readonly evidence: readonly I1VerificationEvidence[];
  readonly expectedTarget: I1RepositoryRevisionIdentity;
  readonly mergeGate: {
    readonly conditions: readonly I1MergeGateCondition[];
    readonly action: I1ProtectedActionAvailability;
  };
  readonly mergedResult?: I1MergedResultIdentity;
}

export type I1RealtimeEntityType = "project" | "factory-run" | "change-set" | "work";

export interface I1RealtimeProjectionEnvelope<T> {
  readonly entityType: I1RealtimeEntityType;
  readonly entityId: string;
  readonly revision: number;
  readonly sequence: number;
  readonly observedAt: string;
  readonly payload: T;
}
