/**
 * Phase 0 live process — `npm start`. Boots the single-host rendezvous-relay with REAL security:
 *   • self-signed TLS (dev CA + browser + agent-facing certs),
 *   • the REAL relay-node data plane spliced between a browser WSS listener (:8443) and an agent
 *     mTLS listener (:8444) — every upgrade runs the real Origin/CSWSH + capability verify + DPoP
 *     path (P5 `onUpgrade`),
 *   • an in-memory control-plane (:8080, best-effort).
 * Prints a ready URL + a freshly-minted browser capability token + the tenant subdomain.
 *
 * A FULL browser click-through is NOT expected in Phase 0: browsers can't attach the DPoP header
 * to a WS upgrade, and no agent tunnel is dialed here yet (P3). This process proves the servers
 * boot and the authz/splice pipeline is wired end to end.
 */
import { createAuthorizer } from './wiring/authorizer.js'
import { buildDataPlane, makeDataPlaneConfig } from './wiring/data-plane.js'
import { buildPhase0World } from './wiring/relay-world.js'
import { generateDevCerts } from './certs/dev-certs.js'
import { makeAgentTlsServerFactory } from './servers/agent-tls.js'
import { startBrowserServer } from './servers/browser-server.js'
import { bootControlPlane } from './servers/control-plane-boot.js'

const BIND_HOST = '127.0.0.1'
const BROWSER_PORT = 8443
const AGENT_PORT = 8444
const CONTROL_PLANE_PORT = 8080
// Capability tokens are deliberately short-lived (relay-auth caps connect TTL at 60s).
const TOKEN_TTL_SEC = 60

function landingHtml(subdomain: string): string {
  return `<!doctype html><meta charset="utf-8"><title>relay-run (Phase 0)</title>
<h1>rendezvous-relay · Phase 0 (dev)</h1>
<p>Tenant subdomain: <code>${subdomain}</code></p>
<p>This dev relay boots the REAL data-plane splice + P5 authz. A full terminal click-through needs
a dialed agent tunnel and the browser DPoP transport (Phase 3).</p>`
}

async function main(): Promise<void> {
  const now = () => Math.floor(Date.now() / 1000)
  const world = await buildPhase0World(now())
  const subdomain = world.host.subdomain
  const browserCn = `${subdomain}.${world.baseDomain}`

  const certs = generateDevCerts(browserCn)

  // A real browser's Origin includes the listener port, so the CSWSH allow-list must too
  // (the world's default origin is port-less for the in-process test).
  const allowedOrigins = [`https://${browserCn}:${BROWSER_PORT}`, ...world.allowedOrigins]

  // Real-time authz (token exp / DPoP freshness advance with the wall clock).
  const authorizer = createAuthorizer({
    deps: world.deps,
    allowedOrigins,
    now,
  })

  const config = makeDataPlaneConfig({
    baseDomain: world.baseDomain,
    bindHost: BIND_HOST,
    bindPort: BROWSER_PORT,
    agentBindPort: AGENT_PORT,
  })

  // Boots the agent-facing mTLS server as part of the listener construction.
  const dp = buildDataPlane({
    config,
    authorizer,
    resolver: world.resolver,
    mtls: world.mtls,
    now,
    caBundle: [Buffer.from(certs.caCertPem)],
    onError: (e) => console.error('[data-plane]', e),
    tlsServerFactory: makeAgentTlsServerFactory({
      serverCertPath: certs.agentServerCertPath,
      serverKeyPath: certs.agentServerKeyPath,
      bindHost: BIND_HOST,
      bindPort: AGENT_PORT,
      onListening: () => console.log(`[agent-mtls] listening wss://${BIND_HOST}:${AGENT_PORT}`),
      onError: (e) => console.error('[agent-mtls]', e),
    }),
  })

  const browserServer = startBrowserServer({
    certPath: certs.browserCertPath,
    keyPath: certs.browserKeyPath,
    bindHost: BIND_HOST,
    bindPort: BROWSER_PORT,
    node: dp.node,
    landingHtml: landingHtml(subdomain),
    onListening: () => console.log(`[browser-wss] listening https://${BIND_HOST}:${BROWSER_PORT}`),
    onError: (e) => console.error('[browser-wss]', e),
  })

  let controlPlane: { close(): Promise<void> } | null = null
  try {
    controlPlane = await bootControlPlane({
      publicRaw: world.publicRaw,
      baseDomain: world.baseDomain,
      caCertPath: certs.caCertPath,
      bindHost: BIND_HOST,
      bindPort: CONTROL_PLANE_PORT,
    })
    console.log(`[control-plane] listening http://${BIND_HOST}:${CONTROL_PLANE_PORT} (admin authz fail-closed — sync-verify seam)`)
  } catch (e) {
    console.warn('[control-plane] boot skipped:', e instanceof Error ? e.message : e)
  }

  // Mint a demo browser capability token bound to a fresh DPoP key (the raw token is a bearer
  // secret — dev only; never log real tokens).
  const cap = await world.issueCap({ now: now(), ttl: TOKEN_TTL_SEC })

  console.log('\n=== relay-run Phase 0 READY ===')
  console.log(`Origin      : https://${browserCn}:${BROWSER_PORT}`)
  console.log(`Add to /etc/hosts:  127.0.0.1  ${browserCn}`)
  console.log(`Subdomain   : ${subdomain}   hostId: ${world.host.hostId}`)
  console.log(`Browser cap : ${cap.raw}`)
  console.log(`DPoP proof  : ${cap.dpop.proofJws}`)
  console.log('Note: no agent tunnel is dialed yet → browser upgrades resolve but 1013 (agent offline).')
  console.log('Ctrl-C to stop.\n')

  const shutdown = async (): Promise<void> => {
    console.log('\nshutting down…')
    browserServer.close()
    dp.listener.close()
    if (controlPlane) await controlPlane.close().catch(() => {})
    certs.cleanup()
    process.exit(0)
  }
  process.on('SIGINT', () => void shutdown())
  process.on('SIGTERM', () => void shutdown())
}

main().catch((e) => {
  console.error('fatal:', e)
  process.exit(1)
})
