import { describe, expect, it } from "vitest";
import { unsafeOpaqueId } from "@awp/contracts";
import { factoryDetail, type LiveHierarchy } from "../../apps/web/src/approved-live.js";

function hierarchy(status: "running" | "completed", cleaned = false): LiveHierarchy {
  const projectId = unsafeOpaqueId("project:wip");
  const planRevisionId = unsafeOpaqueId("plan-revision:wip");
  const factoryRunId = unsafeOpaqueId("factory:wip");
  const taskId = unsafeOpaqueId("task:wip");
  const agentRunId = unsafeOpaqueId("agent:wip");
  const attemptId = unsafeOpaqueId("attempt:wip");
  const workspaceId = unsafeOpaqueId("workspace:wip");
  return {
    project: {
      id: projectId,
      name: "WIP",
      repositoryUrl: "https://github.com/platform-modules/awp.git",
      requiredChecks: [],
      status: "active",
    } as never,
    goals: [],
    plans: [],
    planRevisions: [],
    tasks: [
      {
        id: taskId,
        projectId,
        planRevisionId,
        title: "Preserve WIP",
        status: status === "completed" ? "completed" : "executing",
        dependencyIds: [],
        goalIds: [],
        revision: 1,
      } as never,
    ],
    factoryRuns: [{ id: factoryRunId, projectId, planRevisionId, taskId, status, revision: 1 }],
    agentRuns: [
      {
        id: agentRunId,
        factoryRunId,
        taskId,
        agentPrincipalId: unsafeOpaqueId("principal:agent:wip"),
        role: "coder",
        status: "completed",
        revision: 1,
      },
    ],
    attempts: [
      {
        id: attemptId,
        agentRunId,
        workspaceId,
        status: "terminal",
        selection: { kind: "initial", reason: "test" },
        revision: 1,
      },
    ],
    workspaces: [
      {
        id: workspaceId,
        projectId,
        revision: cleaned ? 4 : 3,
        checkpointDigest: "a".repeat(40),
        checkpointedAt: "2026-08-23T02:30:00.000Z",
        checkpointSource: "git-tree",
        checkpointCollectedAt: "2026-08-23T02:30:01.000Z",
        ...(cleaned ? { cleanedAt: "2026-08-23T02:31:00.000Z" } : {}),
      },
    ],
    changeSets: [],
    reviews: [],
    verificationEvidence: [],
    reviewFindings: [],
  } as unknown as LiveHierarchy;
}

describe("approved live FactoryRun WIP projection", () => {
  it("projects the durable content checkpoint and keeps non-terminal cleanup closed", () => {
    const detail = factoryDetail(hierarchy("running"), "factory:wip");
    expect(detail.wip).toMatchObject({
      state: "safe",
      workspaceId: "workspace:wip",
      checkpointIdentity: "a".repeat(40),
      checkpointedAt: "2026-08-23T02:30:00.000Z",
      cleanupAllowed: false,
    });
    expect(detail.wip.reason).toContain("retained until terminal trusted merge");
  });

  it("shows terminal cleanup eligibility and completed cleanup truth", () => {
    const terminal = factoryDetail(hierarchy("completed"), "factory:wip");
    expect(terminal.wip.cleanupAllowed).toBe(true);
    expect(terminal.wip.reason).toContain("terminal cleanup is permitted");

    const cleaned = factoryDetail(hierarchy("completed", true), "factory:wip");
    expect(cleaned.wip).toMatchObject({ state: "safe", cleanupAllowed: false });
    expect(cleaned.wip.reason).toContain("cleaned after terminal trusted merge");
  });
  it("keeps review and correction stages AWP-owned instead of inventing owner action", () => {
    const reviewHierarchy = hierarchy("running") as unknown as {
      tasks: Array<Record<string, unknown>>;
    };
    reviewHierarchy.tasks[0]!.status = "review";
    const review = factoryDetail(reviewHierarchy as unknown as LiveHierarchy, "factory:wip");
    expect(review.work[0]!.attention).toMatchObject({
      code: "independent-review",
      humanActionRequired: false,
    });
    expect(review.work[0]!.nextAction).toMatchObject({
      kind: "automatic",
      code: "independent-review",
    });

    const correctionHierarchy = hierarchy("running") as unknown as {
      tasks: Array<Record<string, unknown>>;
    };
    correctionHierarchy.tasks[0]!.status = "correction";
    const correction = factoryDetail(
      correctionHierarchy as unknown as LiveHierarchy,
      "factory:wip",
    );
    expect(correction.work[0]!.attention).toMatchObject({
      code: "correction",
      humanActionRequired: false,
    });
    expect(correction.work[0]!.nextAction.kind).toBe("automatic");
  });
});
