import {
  unsafeOpaqueId,
  type AgentRunId,
  type AttemptId,
  type ChangeSetId,
  type FactoryRunId,
  type I1ChangeSetReviewReadModel,
  type I1FactoryRunDetailReadModel,
  type PrincipalId,
  type ProjectId,
  type ProviderId,
  type ReviewId,
  type TaskId,
  type WorkspaceId,
} from "@awp/contracts";
import type { C1ProjectOverviewPayload, C1TaskFixturePayload, SurfaceState } from "./model.js";
import { c1ProjectOverviewSnapshot, c1TaskFixtureSnapshot } from "./c1-snapshot.js";

export interface ProjectPageSnapshot {
  readonly surfaceState: SurfaceState;
  readonly revision: number;
  readonly model: C1ProjectOverviewPayload;
  readonly tasks: readonly C1TaskFixturePayload[];
}
export interface FactoryPageSnapshot {
  readonly surfaceState: Exclude<SurfaceState, "empty">;
  readonly revision: number;
  readonly model: I1FactoryRunDetailReadModel;
}
export interface ReviewPageSnapshot {
  readonly surfaceState: Exclude<SurfaceState, "empty">;
  readonly revision: number;
  readonly model: I1ChangeSetReviewReadModel;
}

export interface AwpWebDataSource {
  project(projectId: string): ProjectPageSnapshot;
  factoryRun(factoryRunId: string): FactoryPageSnapshot;
  review(changeSetId: string): ReviewPageSnapshot;
}

const projectId = unsafeOpaqueId<ProjectId>("project-i1");
const ownerId = unsafeOpaqueId<PrincipalId>("principal-owner");
const reviewerId = unsafeOpaqueId<PrincipalId>("principal-reviewer");
const providerId = unsafeOpaqueId<ProviderId>("provider-agent");
const workspaceId = unsafeOpaqueId<WorkspaceId>("ws-fr001-017");
const factoryRunId = unsafeOpaqueId<FactoryRunId>("FR-001");
const agentRunId = unsafeOpaqueId<AgentRunId>("AR-017");
const attempt1 = unsafeOpaqueId<AttemptId>("AT-001");
const attempt2 = unsafeOpaqueId<AttemptId>("AT-002");
const taskIds = ["task-a", "task-b", "task-c", "task-d", "task-e"].map((value) =>
  unsafeOpaqueId<TaskId>(value),
);

const attentionNone = {
  kind: "none" as const,
  code: "none",
  summary: "No owner attention required",
  humanActionRequired: false,
};

const activeFactoryModel = (): I1FactoryRunDetailReadModel => ({
  id: factoryRunId,
  revision: 1,
  projectId,
  planRevisionId: c1TaskFixtureSnapshot[0]!.planRevisionId,
  status: "running",
  stage: "execution",
  lastProgressAt: "2026-08-21T15:46:00Z",
  work: [
    {
      taskId: taskIds[0]!,
      planRevisionId: c1TaskFixtureSnapshot[0]!.planRevisionId,
      title: "Bootstrap environment",
      status: "completed",
      stage: "complete",
      attention: attentionNone,
      nextAction: { kind: "none", code: "complete", summary: "Task complete" },
    },
    {
      taskId: taskIds[1]!,
      planRevisionId: c1TaskFixtureSnapshot[0]!.planRevisionId,
      title: "Implement API",
      status: "executing",
      currentAgentRunId: agentRunId,
      currentActorId: ownerId,
      stage: "tests",
      lastProgressAt: "2026-08-21T15:46:00Z",
      attention: attentionNone,
      nextAction: { kind: "automatic", code: "continue", summary: "Continue AgentRun" },
    },
    {
      taskId: taskIds[2]!,
      planRevisionId: c1TaskFixtureSnapshot[0]!.planRevisionId,
      title: "Build frontend",
      status: "executing",
      stage: "dependencies",
      lastProgressAt: "2026-08-21T15:45:00Z",
      attention: attentionNone,
      nextAction: { kind: "automatic", code: "continue", summary: "Continue AgentRun" },
    },
    {
      taskId: taskIds[3]!,
      planRevisionId: c1TaskFixtureSnapshot[0]!.planRevisionId,
      title: "Integration tests",
      status: "blocked",
      stage: "dependency",
      attention: {
        kind: "none",
        code: "dependency",
        summary: "Waiting for prerequisite Task B",
        humanActionRequired: false,
      },
      nextAction: {
        kind: "automatic",
        code: "dependency-recheck",
        summary: "Dispatch after Task B completes",
      },
    },
    {
      taskId: taskIds[4]!,
      planRevisionId: c1TaskFixtureSnapshot[0]!.planRevisionId,
      title: "Prepare release",
      status: "queued",
      stage: "queued",
      attention: attentionNone,
      nextAction: { kind: "automatic", code: "queue", summary: "Wait for legal dispatch" },
    },
  ],
  agentRuns: [
    {
      id: agentRunId,
      taskId: taskIds[1]!,
      role: "coder",
      status: "active",
      currentAttemptId: attempt1,
      attempts: [
        {
          id: attempt1,
          workspaceId,
          status: "running",
          providerId,
          accountId: "AWP-Dev",
          model: "Claude 3.5 Sonnet",
          selection: { kind: "initial", reason: "initial dispatch" },
        },
      ],
    },
  ],
  retryDisposition: "not-applicable",
  wip: {
    state: "safe",
    workspaceId,
    checkpointIdentity: "a7f3c9e",
    checkpointedAt: "2026-08-21T15:40:00Z",
    preservedFileCount: 14,
    cleanupAllowed: false,
    reason: "Active run owns durable WIP",
  },
  liveExecutorPresent: true,
  historicalAvailable: true,
  continuation: {
    factoryRunId,
    reattachable: true,
    continuationKey: "FR-001:active",
  },
});

const waitingFactoryModel = (): I1FactoryRunDetailReadModel => ({
  ...activeFactoryModel(),
  revision: 2,
  status: "waiting",
  stage: "capacity-wait",
  wait: {
    kind: "capacity",
    code: "provider-capacity",
    summary: "Eligible execution capacity is temporarily unavailable for Task B.",
    since: "2026-08-21T15:47:00Z",
    nextCheckAt: "2026-08-21T15:47:30Z",
  },
  work: activeFactoryModel().work.map((work) =>
    work.taskId === taskIds[1] || work.taskId === taskIds[2]
      ? {
          ...work,
          status: "waiting" as const,
          stage: "capacity-wait",
          wait: {
            kind: "capacity" as const,
            code: "provider-capacity",
            summary: "Paused at a safe checkpoint while capacity is unavailable",
            since: "2026-08-21T15:47:00Z",
          },
          attention: {
            kind: "capacity" as const,
            code: "provider-capacity",
            summary: "AWP owns bounded capacity recovery",
            humanActionRequired: false,
          },
          nextAction: {
            kind: "automatic" as const,
            code: "capacity-recheck",
            summary: "Re-evaluate eligible capacity in 30s",
          },
        }
      : work,
  ),
  continuation: {
    factoryRunId,
    reattachable: true,
    continuationKey: "FR-001:waiting",
  },
});

const recoveryFactoryModel = (liveExecutorPresent = true): I1FactoryRunDetailReadModel => ({
  ...activeFactoryModel(),
  revision: 3,
  status: "retryable",
  reason: "Execution pod for Task B stopped responding after heartbeat expiry.",
  stage: "recovery-ready",
  lastProgressAt: "2026-08-21T15:47:21Z",
  failure: {
    failureClass: "infrastructure",
    cause: "workspace_heartbeat_expired",
    retryDisposition: "automatic",
    exactSourceIdentity: "checkpoint:a7f3c9e",
    occurredAt: "2026-08-21T15:47:21Z",
    partial: false,
  },
  retryDisposition: "automatic",
  work: activeFactoryModel().work.map((work) =>
    work.taskId === taskIds[1]
      ? {
          ...work,
          status: "failed" as const,
          stage: "recovery-ready",
          attention: {
            kind: "transient-recovery" as const,
            code: "retry-ready",
            summary: "Retry is safe from preserved WIP",
            humanActionRequired: false,
          },
          nextAction: { kind: "automatic" as const, code: "retry", summary: "Start Attempt 2" },
        }
      : work.taskId === taskIds[2]
        ? {
            ...work,
            status: "waiting" as const,
            stage: "safe-pause",
            attention: attentionNone,
            nextAction: {
              kind: "automatic" as const,
              code: "resume-after-recovery",
              summary: "Resume after Task B recovery",
            },
          }
        : work,
  ),
  agentRuns: [
    {
      id: agentRunId,
      taskId: taskIds[1]!,
      role: "coder",
      status: "waiting",
      reason: "Attempt 1 failed; preserved WIP is retryable",
      currentAttemptId: attempt2,
      attempts: [
        {
          id: attempt1,
          workspaceId,
          status: "terminal",
          providerId,
          accountId: "AWP-Dev",
          model: "Claude 3.5 Sonnet",
          selection: { kind: "initial", reason: "initial dispatch" },
        },
        {
          id: attempt2,
          workspaceId,
          status: "created",
          providerId,
          accountId: "AWP-Dev",
          model: "Claude 3.5 Sonnet",
          selection: {
            kind: "retry",
            reason: "recover preserved WIP",
            previousAttemptId: attempt1,
          },
        },
      ],
    },
  ],
  liveExecutorPresent,
  historicalAvailable: true,
  continuation: {
    factoryRunId,
    reattachable: true,
    continuationKey: "FR-001:attempt-2",
  },
});

const reviewModel = (
  state: "changes-requested" | "verifying" | "ready-to-merge" | "merged",
): I1ChangeSetReviewReadModel => {
  const approved = state !== "changes-requested";
  const ready = state === "ready-to-merge" || state === "merged";
  const merged = state === "merged";
  const changeSetId = unsafeOpaqueId<ChangeSetId>(approved ? "CS-002" : "CS-001");
  const reviewId = unsafeOpaqueId<ReviewId>(approved ? "RV-002" : "RV-001");
  const candidateDigest = approved ? "94c11bf" : "8bd27ae";
  const findings = approved
    ? []
    : [
        {
          id: "cross-plan",
          severity: "blocking" as const,
          summary: "Cross-Plan prerequisite omitted from legal range",
          source: "src/application/queue.ts:152",
          resolved: false,
        },
        {
          id: "error-copy",
          severity: "recommendation" as const,
          summary: "Error copy should name prerequisite",
          source: "src/ui/queue-dnd.ts:84",
          resolved: false,
        },
      ];
  const evidence = [
    {
      id: "domain-tests",
      name: "Domain tests",
      state: "passed" as const,
      source: "debian1",
      observedAt: "2026-08-21T16:05:00Z",
      candidateDigest,
    },
    {
      id: "architecture",
      name: "Architecture check",
      state: "passed" as const,
      source: "debian1",
      observedAt: "2026-08-21T16:05:00Z",
      candidateDigest,
    },
  ];
  return {
    id: changeSetId,
    revision: approved ? 2 : 1,
    projectId,
    taskId: taskIds[3]!,
    status: merged
      ? "merged"
      : ready
        ? "ready-to-merge"
        : state === "verifying"
          ? "verifying"
          : "changes-requested",
    baseIdentity: "faec4c7",
    candidateDigest,
    candidate: {
      treeDigest: candidateDigest,
      patchDigest: `patch-${candidateDigest}`,
      changedPaths: [
        "src/application/queue.ts",
        "src/domain/task.ts",
        "src/domain/dependency.ts",
        "src/ui/queue-dnd.ts",
        "tests/queue.test.ts",
        "docs/queue.md",
      ],
      changes: [
        { path: "src/application/queue.ts", kind: "modify" },
        { path: "src/domain/task.ts", kind: "modify" },
        { path: "src/domain/dependency.ts", kind: "add" },
        { path: "src/ui/queue-dnd.ts", kind: "modify" },
        { path: "tests/queue.test.ts", kind: "modify" },
        { path: "docs/queue.md", kind: "add" },
      ],
    },
    reviews: [
      {
        id: reviewId,
        reviewerPrincipalId: reviewerId,
        status: "submitted",
        disposition: approved ? "approved" : "changes-requested",
      },
    ],
    findings,
    evidence,
    expectedTarget: { reference: "refs/heads/main", revision: ready ? "faec4c7" : "faec4c7" },
    mergeGate: {
      conditions: [
        { code: "candidate-state", satisfied: ready, summary: "Exact candidate is ready" },
        {
          code: "review",
          satisfied: approved,
          summary: approved ? "Independent Review approved" : "Blocking Review finding remains",
        },
        {
          code: "evidence",
          satisfied: state !== "verifying",
          summary:
            state === "verifying"
              ? "Required repository check is pending"
              : "Required evidence is current",
        },
        {
          code: "provider-checks",
          satisfied: state !== "verifying",
          summary:
            state === "verifying"
              ? "Repository-required CI check is pending"
              : "Repository-required checks passed",
        },
        { code: "publication", satisfied: true, summary: "Publication fidelity verified" },
        {
          code: "policy",
          satisfied: true,
          summary: "I1 default full-chain policy authorizes trusted merge",
        },
        {
          code: "authority",
          satisfied: true,
          summary: "Trusted control-plane authority available",
        },
        {
          code: "target-revision",
          satisfied: true,
          summary: "Expected target revision is current",
        },
      ],
      action: merged
        ? { available: false, reasonCode: "terminal", summary: "ChangeSet is already merged" }
        : ready
          ? {
              available: false,
              reasonCode: "ready",
              summary: "Trusted Merge continues automatically",
            }
          : state === "verifying"
            ? {
                available: false,
                reasonCode: "provider-checks",
                summary: "Repository-required CI check is pending",
              }
            : {
                available: false,
                reasonCode: "review",
                summary: "Blocking Review finding remains",
              },
    },
    ...(merged
      ? {
          mergedResult: {
            target: { reference: "refs/heads/main", revision: "4b8e2c1" },
            mergedAt: "2026-08-21T16:08:00Z",
            mergedBy: ownerId,
          },
        }
      : {}),
  };
};

/**
 * Deterministic contract-shaped source used only for development/render tests.
 * Production integration supplies the same transport-safe authoritative read-model
 * shapes from the control plane; URL parameters never promote lifecycle state.
 */
export const deterministicC1DataSource: AwpWebDataSource = {
  project: () => ({
    surfaceState: "ready",
    revision: 1,
    model: c1ProjectOverviewSnapshot,
    tasks: c1TaskFixtureSnapshot,
  }),
  factoryRun: () => ({ surfaceState: "ready", revision: 1, model: activeFactoryModel() }),
  review: (changeSetId) => ({
    surfaceState: "ready",
    revision: changeSetId === "CS-002" ? 2 : 1,
    model: reviewModel(changeSetId === "CS-002" ? "ready-to-merge" : "changes-requested"),
  }),
};

export function fixtureDataSource(mode: string | undefined): AwpWebDataSource {
  if (!mode) return deterministicC1DataSource;
  return {
    project: () => ({
      surfaceState:
        mode === "project-loading"
          ? "loading"
          : mode === "project-error"
            ? "error"
            : mode === "project-stale"
              ? "stale"
              : mode === "project-permission"
                ? "permission"
                : mode === "project-empty"
                  ? "empty"
                  : "ready",
      revision: 1,
      model: c1ProjectOverviewSnapshot,
      tasks: c1TaskFixtureSnapshot,
    }),
    factoryRun: () => ({
      surfaceState:
        mode === "factory-loading"
          ? "loading"
          : mode === "factory-error"
            ? "error"
            : mode === "factory-stale" || mode === "recovery-stale"
              ? "stale"
              : mode === "factory-permission"
                ? "permission"
                : "ready",
      revision:
        mode.startsWith("recovery") || mode === "history-no-executor"
          ? 3
          : mode === "waiting"
            ? 2
            : 1,
      model:
        mode.startsWith("recovery") || mode === "history-no-executor"
          ? recoveryFactoryModel(!(mode === "recovery-stale" || mode === "history-no-executor"))
          : mode === "waiting"
            ? waitingFactoryModel()
            : activeFactoryModel(),
    }),
    review: (changeSetId) => ({
      surfaceState:
        mode === "review-loading"
          ? "loading"
          : mode === "review-error"
            ? "error"
            : mode === "review-stale"
              ? "stale"
              : mode === "review-permission"
                ? "permission"
                : "ready",
      revision:
        mode === "merged" ||
        mode === "ready-to-merge" ||
        mode === "verifying" ||
        changeSetId === "CS-002"
          ? 2
          : 1,
      model: reviewModel(
        mode === "merged"
          ? "merged"
          : mode === "verifying"
            ? "verifying"
            : mode === "ready-to-merge" || changeSetId === "CS-002"
              ? "ready-to-merge"
              : "changes-requested",
      ),
    }),
  };
}
