import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
import { unsafeOpaqueId, type WorkspaceId } from "@awp/contracts";
import {
  buildWorkspaceResources,
  type WorkspaceExecutionProfile,
} from "../../../packages/providers/workspace-kubernetes/src/index.js";

const root = resolve(import.meta.dirname, "../../..");
const read = (path: string) => readFileSync(resolve(root, path), "utf8");

const safeProfile: WorkspaceExecutionProfile = {
  key: "secure",
  namespace: "awp-workspaces",
  image: "node:24-bookworm",
  runtimeClassName: "gvisor",
  persistent: true,
  storageSize: "2Gi",
  requests: { cpu: "250m", memory: "512Mi" },
  limits: { cpu: "2", memory: "4Gi" },
  allowedEgressCidrs: [],
  allowDns: true,
  secretProjections: [],
  provenance: { image: "test" },
};

describe("execution-plane security invariants", () => {
  it("rejects publication, merge and production credential projections before pod creation", () => {
    for (const purpose of ["git-publication", "merge.execute", "production-deploy-token"]) {
      const profile: WorkspaceExecutionProfile = {
        ...safeProfile,
        secretProjections: [{ secretName: "forbidden", mountPath: "/run/forbidden", purpose }],
      };
      expect(() =>
        buildWorkspaceResources(unsafeOpaqueId<WorkspaceId>("workspace-security"), profile),
      ).toThrow(/credential forbidden/i);
    }
  });

  it("limits workspace-controller secret authority to get-only on the registry pull credential", () => {
    const rbac = read("infra/k8s/execution-base.yaml");
    expect(rbac).toContain(
      'resources: ["pods", "pods/log", "persistentvolumeclaims", "services", "serviceaccounts"]',
    );
    expect(rbac).toMatch(
      /resources:\s*\["secrets"\]\s*resourceNames:\s*\["awp-ghcr-pull"\]\s*verbs:\s*\["get"\]/,
    );
    const secretRule = rbac.match(
      /resources:\s*\["secrets"\]\s*resourceNames:\s*\["awp-ghcr-pull"\]\s*verbs:\s*\[([^\]]+)\]/,
    );
    expect(secretRule?.[1]?.trim()).toBe('"get"');
    expect(rbac).not.toMatch(/pods\/exec/);
    expect(rbac).not.toMatch(/cluster-admin/);
    expect(rbac).not.toMatch(/kind: ClusterRoleBinding/);
  });

  it("establishes namespace default-deny networking and per-workspace explicit egress", () => {
    const base = read("infra/k8s/execution-base.yaml");
    expect(base).toContain("name: default-deny");
    expect(base).toContain("policyTypes: [Ingress, Egress]");
    expect(base).toContain("egress: []");

    const resources = buildWorkspaceResources(
      unsafeOpaqueId<WorkspaceId>("workspace-network"),
      safeProfile,
    );
    const egress = resources.networkPolicy.spec?.egress as readonly unknown[];
    expect(egress).toHaveLength(1); // DNS only; no arbitrary 0.0.0.0/0 egress.
    expect(JSON.stringify(egress)).not.toContain("0.0.0.0/0");
  });

  it("keeps normal workspace and ARC runner manifests free of reusable Git publication credentials", () => {
    const files = [
      "packages/providers/workspace-kubernetes/src/resources.ts",
      "infra/arc/scale-set-untrusted-values.yaml",
      "infra/arc/scale-set-trusted-values.yaml",
      "infra/k8s/execution-base.yaml",
    ];
    for (const path of files) {
      const source = read(path);
      expect(source).not.toMatch(
        /GH_TOKEN\s*[:=]|GITHUB_TOKEN\s*[:=]|github_pat_|ghp_|BEGIN (RSA|PRIVATE) KEY/,
      );
    }
    expect(read("infra/arc/scale-set-untrusted-values.yaml")).toContain(
      "automountServiceAccountToken: false",
    );
  });

  it("keeps GitHub CI transport incapable of ref publication or merge mutation", () => {
    const source = read("packages/providers/ci-github/src/github.ts");
    expect(source).toContain("actions/workflows");
    expect(source).toContain("actions/runs");
    expect(source).not.toMatch(/git\/refs|pulls\/.*merge|merges|createRef|updateRef/);
  });
});
