// Responsibility: expose the YAML-owned sentinel internal publish capability without claiming provenance.
import { rootPath } from "./config";
import type { CicdDeliveryAuthority } from "./cicd-delivery-authority";
import type { WebProbeSentinelOptions } from "./hwlab-node-web-sentinel-cicd-shared";
import { readYamlRecord } from "./platform-infra-ops-library";
import { materializeYamlComposition } from "./yaml-composition";

const configPath = "config/platform-infra/pipelines-as-code.yaml";
const configRef = `${configPath}#capabilities.sentinelInternalPublish`;

export interface SentinelPacInternalPublishCapability {
  readonly enabled: boolean;
  readonly admissionProvenance: "unavailable";
  readonly trackingIssue: string;
  readonly configRef: string;
  readonly valuesPrinted: false;
}

export type SentinelPacInternalPublishAuthorization = {
  readonly allowed: false;
  readonly mode: "sentinel-pac-internal-publish-blocked";
  readonly reason:
    | "operator-entrypoint"
    | "delivery-authority-not-pac"
    | "capability-disabled"
    | "admission-provenance-unavailable";
  readonly capability: SentinelPacInternalPublishCapability;
  readonly valuesPrinted: false;
};

export function readSentinelPacInternalPublishCapability(): SentinelPacInternalPublishCapability {
  const raw = readYamlRecord<Record<string, unknown>>(rootPath(...configPath.split("/")), "platform-infra-pipelines-as-code");
  const composed = materializeYamlComposition(raw, { label: configPath }).value;
  const capabilities = record(composed.capabilities, `${configPath}#capabilities`);
  const capability = record(capabilities.sentinelInternalPublish, configRef);
  const enabled = booleanField(capability.enabled, `${configRef}.enabled`);
  const admissionProvenance = stringField(capability.admissionProvenance, `${configRef}.admissionProvenance`);
  if (admissionProvenance !== "unavailable") {
    throw new Error(`${configRef}.admissionProvenance must remain unavailable until the admission contract is implemented`);
  }
  const trackingIssue = stringField(capability.trackingIssue, `${configRef}.trackingIssue`);
  if (!/^https:\/\/github\.com\/pikasTech\/unidesk\/issues\/\d+$/u.test(trackingIssue)) {
    throw new Error(`${configRef}.trackingIssue must reference the owning GitHub issue`);
  }
  return {
    enabled,
    admissionProvenance,
    trackingIssue,
    configRef,
    valuesPrinted: false,
  };
}

export function authorizeSentinelPacInternalPublish(
  options: WebProbeSentinelOptions,
  authority: CicdDeliveryAuthority,
  capability = readSentinelPacInternalPublishCapability(),
): SentinelPacInternalPublishAuthorization {
  if (options.kind !== "publish" || options.internalExecution !== "pac-controller") {
    return denied("operator-entrypoint", capability);
  }
  if (authority.kind !== "pac-pr-merge") return denied("delivery-authority-not-pac", capability);
  if (!capability.enabled) return denied("capability-disabled", capability);
  return denied("admission-provenance-unavailable", capability);
}

function denied(
  reason: SentinelPacInternalPublishAuthorization["reason"],
  capability: SentinelPacInternalPublishCapability,
): SentinelPacInternalPublishAuthorization {
  return {
    allowed: false,
    mode: "sentinel-pac-internal-publish-blocked",
    reason,
    capability,
    valuesPrinted: false,
  };
}

function record(value: unknown, path: string): Record<string, unknown> {
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${path} must be an object`);
  return value as Record<string, unknown>;
}

function booleanField(value: unknown, path: string): boolean {
  if (typeof value !== "boolean") throw new Error(`${path} must be a boolean`);
  return value;
}

function stringField(value: unknown, path: string): string {
  if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${path} must be a non-empty string`);
  return value.trim();
}
