/**
 * Process entrypoint. Loads + validates config (fail-closed), wires the REAL collaborators (CP
 * client over CP_URL, lazy manage-token minter reading the PKCS#8 capability key), and binds the
 * app to LOOPBACK ONLY (127.0.0.1) — the admin panel must never listen on a public interface.
 *
 * Logging here is deliberately minimal and secret-free: only the bind address/port and startup
 * errors (never the password, session secret, key material, or any minted token) are printed.
 */
import { fileURLToPath } from 'node:url'
import { dirname, resolve } from 'node:path'
import { loadConfig, PANEL_BIND_HOST } from './config.js'
import { createCpClient } from './cp-client.js'
import { createManageTokenMinter } from './manage-token.js'
import { buildApp } from './app.js'

const HERE = dirname(fileURLToPath(import.meta.url))
/** Built SPA lives at control-panel/public/build (sibling of src/). */
const STATIC_ROOT = resolve(HERE, '..', 'public', 'build')

async function main(): Promise<void> {
  const config = loadConfig(process.env)
  const cpClient = createCpClient({ cpUrl: config.cpUrl })
  const minter = createManageTokenMinter({
    capabilitySignKeyPath: config.capabilitySignKeyPath,
    baseDomain: config.baseDomain,
    operatorAccountId: config.operatorAccountId,
  })

  const app = await buildApp({
    config,
    cpClient,
    minter,
    staticRoot: STATIC_ROOT,
    // Structured, secret-free server log for upstream failures.
    logError: (message: string) => process.stderr.write(`[control-panel] ${message}\n`),
  })

  await app.listen({ host: PANEL_BIND_HOST, port: config.panelBindPort })
  process.stdout.write(`[control-panel] listening on http://${PANEL_BIND_HOST}:${config.panelBindPort}\n`)
}

main().catch((err: unknown) => {
  process.stderr.write(`[control-panel] fatal: ${err instanceof Error ? err.message : String(err)}\n`)
  process.exit(1)
})
