import { readFileSync, readdirSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { I1_CONFIGURATION_DEFINITIONS } from "@awp/config";
import { verificationEvidenceReferenceResolvable } from "@awp/domain";
import { unsafeOpaqueId, type ProviderId, type WorkspaceId } from "@awp/contracts";

const candidate = "a".repeat(40);

describe("I1 verification pain invariants", () => {
  it("evidence-references-are-immutable-and-resolvable", () => {
    expect(
      verificationEvidenceReferenceResolvable(candidate, {
        kind: "workspace-checkpoint",
        workspaceId: unsafeOpaqueId<WorkspaceId>("workspace:verification"),
        checkpointDigest: candidate,
        observedAt: "2026-08-24T05:00:00.000Z",
      }),
    ).toBe(true);
    expect(
      verificationEvidenceReferenceResolvable(candidate, {
        kind: "provider-observation",
        providerReference: {
          providerId: unsafeOpaqueId<ProviderId>("provider:required-checks"),
          resourceType: "required-check-snapshot",
          nativeId: "platform-modules/awp@deadbeef",
          nativeRevision: "deadbeef",
          observedAt: "2026-08-24T05:00:00.000Z",
        },
      }),
    ).toBe(true);
    expect(verificationEvidenceReferenceResolvable(candidate, undefined)).toBe(false);
  });

  it("evidence-invalidated-by-changeset-revision", () => {
    expect(
      verificationEvidenceReferenceResolvable("b".repeat(40), {
        kind: "workspace-checkpoint",
        workspaceId: unsafeOpaqueId<WorkspaceId>("workspace:verification"),
        checkpointDigest: candidate,
        observedAt: "2026-08-24T05:00:00.000Z",
      }),
    ).toBe(false);
  });

  it("done-requires-verification-evidence", () => {
    const execution = readFileSync("packages/application/src/execution.ts", "utf8");
    expect(execution).toContain("verificationEvidenceReferenceResolvable");
    expect(execution).toContain(
      "Required VerificationEvidence requires an immutable evidence reference",
    );
    expect(execution).toContain("Merge requires current passing required VerificationEvidence");
  });

  it("agent-self-report-cannot-transition-state", () => {
    const execution = readFileSync("packages/application/src/execution.ts", "utf8");
    expect(execution).not.toMatch(/completion(?:Text|Narration|Claim)/u);
    expect(execution).toContain(
      "Attempt completion requires timestamped required VerificationEvidence",
    );
    expect(execution).toContain(
      "Attempt completion Workspace checkpoint must equal the collected candidate tree",
    );
  });

  it("verification-not-rerun-when-inputs-unchanged", () => {
    const execution = readFileSync("packages/application/src/execution.ts", "utf8");
    expect(execution).toContain("observeRequiredChecks");
    expect(execution).not.toContain("CIProvider");
    expect(execution).toContain("awp-i1-automerge-required-checks-observe");
  });
});

describe("I1 autonomy/policy applicability", () => {
  it("approval-points-are-policy-declared", () => {
    const applicationFiles = readdirSync("packages/application/src")
      .filter((name) => name.endsWith(".ts"))
      .map((name) => readFileSync(`packages/application/src/${name}`, "utf8"))
      .join("\n");
    expect(applicationFiles).not.toMatch(/tx\.approvals|approvals\.(?:insert|update)/u);
    const app = readFileSync("apps/control-plane/src/app.ts", "utf8");
    expect(app).toContain("/plans/:planId/approve");
  });

  it("default-policy-has-no-hitl-hooks", () => {
    const approvedLive = readFileSync("apps/web/src/approved-live.ts", "utf8");
    expect(approvedLive).toContain(
      "Default full-chain policy authorizes trusted merge without another owner approval",
    );
    expect(approvedLive).toContain("humanActionRequired: false");
    expect(
      I1_CONFIGURATION_DEFINITIONS.some((definition) =>
        /hitl|approval|policy/i.test(definition.key),
      ),
    ).toBe(false);
  });

  it("pause-requires-authority-boundary", () => {
    const approvedLive = readFileSync("apps/web/src/approved-live.ts", "utf8");
    expect(approvedLive).not.toContain("humanActionRequired: true");
    const project = readFileSync("apps/web/src/render-project.ts", "utf8");
    expect(project).toContain("explicit owner launch boundary");
    expect(project).toContain("Execution account required");
  });

  it("hitl-hooks-are-configurable-per-project is an I3 activation gate", () => {
    const pain = readFileSync("docs/plans/AWP-PAIN-INVARIANTS.md", "utf8");
    expect(pain).toContain("**I3 activation gate.**");
    expect(pain).toContain("I1 must not fake this product surface");
    expect(I1_CONFIGURATION_DEFINITIONS.some((definition) => /hitl/i.test(definition.key))).toBe(
      false,
    );
  });
});
