/**
 * T15 — CA-key / secret-manager bootstrap + KMS-signer factory (§3.1). The intermediate
 * leaf-signing key is a non-exportable KMS/HSM key: signing is a `sign()` CALL, the raw private
 * key is NEVER loaded into control-plane memory. `buildCaSigner` FAILS FAST at startup (INV9) if
 * the key ref is unresolvable OR its policy does not restrict `sign` to the control-plane
 * service principal. Both T8 `signHostLeaf` and T15 `renewHostLeaf` call this shared primitive —
 * neither loads a raw key.
 */
import { createPublicKey } from 'node:crypto'
import type { ControlPlaneEnv } from '../env.js'
import { ed25519Sign, generateEd25519, type KeyObject } from '../util/crypto.js'

/** Wraps KMS `sign()`; no raw key ever crosses this boundary. */
export interface CaSigner {
  sign(tbsCert: Uint8Array): Promise<Uint8Array>
  /** Public verifying key of the CA (for tests / chain assembly). */
  readonly publicKeyRaw: Uint8Array
}

/**
 * KMS resolver seam. Production resolves a real KMS/HSM key handle + policy; tests inject a fake.
 * A resolver returns `{ canSign, policyRestrictedToServicePrincipal }` for the given ref, or throws
 * if the ref cannot be resolved at all.
 */
export interface KmsResolver {
  resolve(keyRef: string): Promise<{
    readonly signer: CaSigner
    readonly policyRestrictedToServicePrincipal: boolean
  }>
}

/**
 * Build the CA signer for the configured intermediate KMS key. Fail-fast (INV9, §3.1):
 *  - throws if the resolver cannot resolve the ref;
 *  - throws if the KMS key policy is broader than the control-plane service principal.
 */
export async function buildCaSigner(env: ControlPlaneEnv, resolver: KmsResolver): Promise<CaSigner> {
  let resolved
  try {
    resolved = await resolver.resolve(env.caIntermediateKmsKeyRef)
  } catch (err: unknown) {
    // Never log the ref VALUE — only that resolution failed (INV9).
    throw new Error(
      `CA intermediate KMS key could not be resolved: ${err instanceof Error ? err.message : 'unknown'}`,
    )
  }
  if (!resolved.policyRestrictedToServicePrincipal) {
    throw new Error(
      'CA intermediate KMS key policy is broader than the control-plane service principal (§3.1) — refusing to boot',
    )
  }
  return resolved.signer
}

/**
 * In-process Ed25519 CA signer — TEST/DEV ONLY (clearly NOT a KMS; the plan mandates a real
 * non-exportable KMS key in production, §3.1). Exposes the same `sign()` surface so callers are
 * KMS-shaped and never touch a raw key path themselves.
 */
export function inProcessCaSigner(privateKey?: KeyObject): CaSigner {
  const key = privateKey ?? generateEd25519().privateKey
  const pub = derivePublicRaw(key)
  return {
    publicKeyRaw: pub,
    async sign(tbsCert) {
      return ed25519Sign(key, tbsCert)
    },
  }
}

function derivePublicRaw(privateKey: KeyObject): Uint8Array {
  // Recover the raw 32-byte Ed25519 public key from the private KeyObject.
  const spki = createPublicKey(privateKey).export({ format: 'der', type: 'spki' }) as Buffer
  return new Uint8Array(spki.subarray(spki.length - 32))
}
