/**
 * RELAY-PHASE1 · staging admin-token minter (run from relay-run/ so relay-auth resolves).
 *
 *   cd relay-run && npx tsx scripts/mint-manage-token.ts --aud <BASE_DOMAIN> [--sub <accountId>]
 *
 * Mints a §4.3 `manage` capability token signed by the P5 PRIVATE key, for the deny-by-default
 * control-plane admin API (POST /accounts, /accounts/:id/pairing-codes). `aud` MUST equal the CP's
 * BASE_DOMAIN (its `expectedAud`). The admin API verifies signature+aud+rights and derives accountId
 * ONLY from the token (INV3) — it does NOT require a live DPoP proof — but the issuer still stamps a
 * well-formed `cnf.jkt` (from a throwaway ephemeral key) because issueCapabilityToken mandates it.
 * TTL is clamped to 60 s, so mint immediately before each admin call.
 *
 * Prints ONLY the raw token to stdout; the signing key material is never printed.
 */
import { readFileSync } from 'node:fs'
import { issueCapabilityToken } from 'relay-auth'
import { generateEd25519KeyPair, exportEd25519PublicRaw } from 'relay-auth/src/crypto/ed25519.js'
import { jwkThumbprint } from 'relay-auth/src/crypto/thumbprint.js'

function arg(name: string, fallback?: string): string | undefined {
  const i = process.argv.indexOf(`--${name}`)
  return i >= 0 && i + 1 < process.argv.length ? process.argv[i + 1] : fallback
}

async function main(): Promise<void> {
  const keyPath = arg('key', '/etc/relay/capability/capability-sign.key.pem') as string
  const aud = arg('aud')
  const sub = arg('sub', 'bootstrap') as string
  const host = arg('host', '_manage_') as string
  const rights = (arg('rights', 'manage') as string).split(',').map((r) => r.trim())
  if (aud === undefined || aud.length === 0) {
    process.stderr.write('FATAL: --aud <BASE_DOMAIN> is required\n')
    process.exit(2)
  }

  const pem = readFileSync(keyPath, 'utf8')
  const der = Buffer.from(pem.replace(/-----[^-]+-----/g, '').replace(/\s+/g, ''), 'base64')
  const signingKey = await globalThis.crypto.subtle.importKey('pkcs8', der, { name: 'Ed25519' }, false, ['sign'])

  const eph = await generateEd25519KeyPair()
  const cnfJkt = await jwkThumbprint(await exportEd25519PublicRaw(eph.publicKey))
  const now = Math.floor(Date.now() / 1000)

  const token = await issueCapabilityToken(
    // Runtime only reads principal.accountId; a minimal shape is intentional for this staging tool.
    { principal: { accountId: sub } as never, aud, host, rights: rights as never, ttlSeconds: 60, cnfJkt },
    signingKey,
    now,
  )
  process.stdout.write(token)
}

main().catch((e: unknown) => {
  process.stderr.write(`mint failed: ${e instanceof Error ? e.message : String(e)}\n`)
  process.exit(1)
})
