import { createHash, createPrivateKey, createPublicKey } from 'node:crypto'
import { readFile, stat } from 'node:fs/promises'
import { resolve } from 'node:path'

const root = resolve(new URL('..', import.meta.url).pathname)
export const defaultKeyId = 'bitbybit-local-release-2026'
export const defaultPrivateKeyPath = resolve(root, '.secrets/release-signing-private.pem')
export const publicKeyPath = resolve(root, 'config/release-signing-public.pem')

const normalizePem = (value) => value.replace(/\r\n/g, '\n').trim()

export const loadControlledSigningKey = async () => {
  const envKey = process.env.RELEASE_SIGNING_PRIVATE_KEY
  const envKeyId = process.env.RELEASE_SIGNING_KEY_ID
  if (envKey && !envKeyId?.trim()) throw new Error('RELEASE_SIGNING_KEY_ID is required when RELEASE_SIGNING_PRIVATE_KEY is provided.')
  const configuredPath = process.env.RELEASE_SIGNING_PRIVATE_KEY_PATH
  const keyPath = configuredPath ? resolve(root, configuredPath) : defaultPrivateKeyPath
  let privateKeyPem = envKey
  let source = 'environment'
  if (!privateKeyPem) {
    const stats = await stat(keyPath).catch(() => undefined)
    if (!stats?.isFile()) throw new Error(`Controlled release signing key is missing: ${keyPath}`)
    if ((stats.mode & 0o077) !== 0) throw new Error(`Controlled release signing key must be mode 600: ${keyPath}`)
    privateKeyPem = await readFile(keyPath, 'utf8')
    source = keyPath
  }
  const keyId = (envKeyId || defaultKeyId).trim()
  if (!keyId) throw new Error('RELEASE_SIGNING_KEY_ID must be non-empty.')
  let privateKey
  try { privateKey = createPrivateKey(privateKeyPem) } catch (error) { throw new Error(`Controlled release signing key is invalid: ${error instanceof Error ? error.message : String(error)}`) }
  if (privateKey.asymmetricKeyType !== 'ed25519') throw new Error(`Controlled release signing key must be Ed25519 (got ${privateKey.asymmetricKeyType || 'unknown'}).`)
  const derivedPublicKeyPem = createPublicKey(privateKey).export({ type: 'spki', format: 'pem' }).toString()
  const configuredPublicKeyPem = await readFile(publicKeyPath, 'utf8').catch(() => { throw new Error(`Release signing public key is missing: ${publicKeyPath}`) })
  if (normalizePem(derivedPublicKeyPem) !== normalizePem(configuredPublicKeyPem)) throw new Error(`Controlled private key does not match ${publicKeyPath}. Rotate both keys together.`)
  return { privateKeyPem, keyId, source, publicKeyPem: configuredPublicKeyPem, publicKeySha256: createHash('sha256').update(normalizePem(configuredPublicKeyPem)).digest('hex') }
}
