import { createHash } from "node:crypto";

import { readPacAdmissionContract } from "./platform-infra-pac-provenance";

export interface PacConsumerRbacDesiredIdentity {
  readonly configSha256: string;
  readonly namespaces: readonly string[];
}

const pacConsumerReadOnlyRules = [
  { apiGroups: ["tekton.dev"], resources: ["pipelineruns", "taskruns"], verbs: ["get", "list", "watch"] },
  { apiGroups: [""], resources: ["pods", "pods/log"], verbs: ["get", "list", "watch"] },
] as const;

const pacConsumerDefaultRoleRef = { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "unidesk-pac-consumer-runner" } as const;

export function renderPacConsumerRbacDesiredFragment(targetId: string): string {
  const consumers = readPacAdmissionContract().consumers.filter((consumer) => consumer.node.toLowerCase() === targetId.toLowerCase());
  const namespaces = [...new Set(consumers.map((consumer) => consumer.namespace))];
  if (namespaces.length === 0) return "";
  const configSha256 = pacConsumerRbacDesiredIdentity(targetId).configSha256;
  const objects = namespaces.flatMap((namespace) => {
    const labels = {
      "app.kubernetes.io/managed-by": "unidesk",
      "app.kubernetes.io/part-of": "platform-infra",
      "unidesk.ai/pac-rbac-contract": "admission-provenance-required",
    };
    const annotations = {
      "argocd.argoproj.io/sync-wave": "-1",
      "unidesk.ai/effective-config-sha256": configSha256,
    };
    return [
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "Role",
        metadata: { name: "unidesk-pac-consumer-runner", namespace, labels, annotations },
        rules: pacConsumerReadOnlyRules,
      },
      {
        apiVersion: "rbac.authorization.k8s.io/v1",
        kind: "RoleBinding",
        metadata: { name: "unidesk-pac-consumer-runner-default", namespace, labels, annotations },
        subjects: [{ kind: "ServiceAccount", name: "default", namespace }],
        roleRef: pacConsumerDefaultRoleRef,
      },
    ];
  });
  return `${objects.map((item) => Bun.YAML.stringify(item).trim()).join("\n---\n")}\n`;
}

export function pacConsumerRbacDesiredIdentity(targetId: string): PacConsumerRbacDesiredIdentity {
  const consumers = readPacAdmissionContract().consumers.filter((consumer) => consumer.node.toLowerCase() === targetId.toLowerCase());
  const namespaces = [...new Set(consumers.map((consumer) => consumer.namespace))].sort();
  const desiredSpec = namespaces.map((namespace) => ({
    namespace,
    role: { name: "unidesk-pac-consumer-runner", rules: pacConsumerReadOnlyRules },
    roleBinding: {
      name: "unidesk-pac-consumer-runner-default",
      subjects: [{ kind: "ServiceAccount", name: "default", namespace }],
      roleRef: pacConsumerDefaultRoleRef,
    },
  }));
  return {
    configSha256: `sha256:${createHash("sha256").update(JSON.stringify({ targetId, desiredSpec, contract: "admission-provenance-required-v1" })).digest("hex")}`,
    namespaces,
  };
}
