import { createRouter } from '../../create-router';
import { getHeadscaleServerUrl } from '../headscale/router';

// Enrollment for OffTail, the in-app Tailscale. Authenticate the owner, forward to officer-headscale, and
// hold no Headscale knowledge whatsoever — no URL, no admin key, no user name.
//
// This file used to mint the pre-auth key itself, from HEADSCALE_URL / HEADSCALE_API_KEY / HEADSCALE_USER
// read out of the host env. Three globals describe exactly one server; Officer keeps a registry of many in
// `headscale_servers`, one active at a time, so the env could contradict the server the owner had selected.
// The two credential vars were later removed and the failure was silent — `if (!base || !apiKey)` returned
// 503 before the rest of the route ever ran, so enrollment had simply stopped working and said nothing.
// The logic now lives in the sidecar that owns the registry (src/servers/sidecar/headscale/enroll.ts).
//
// It stays mounted at /api/vpn rather than moving under /api/headscale because the path is a contract:
// enrollVpn() in the mobile core POSTs exactly /api/vpn/enroll. createSidecarProxy strips its own prefix
// and cannot express that rewrite, so this one forward is spelled out by hand.

export const vpnRouter = createRouter();

// POST /api/vpn/enroll → { controlUrl, authKey }
//
// The response shape is the other half of the contract: enrollVpn() in @officer/core destructures exactly
// those two fields, so changing them means changing the mobile app too.
vpnRouter.post('/enroll', async (ctx) => {
  const baseUrl = getHeadscaleServerUrl();
  if (!baseUrl) return ctx.json({ error: 'headscale sidecar not available' }, 503);

  // Forwarded verbatim: an optional {userId} picks the owning Headscale user when the server has several.
  const body = await ctx.req.arrayBuffer();

  let upstream: Response;
  try {
    upstream = await fetch(`${baseUrl}/_officer/enroll`, {
      method: 'POST',
      headers: {
        'content-type': ctx.req.header('content-type') ?? 'application/json',
        // The authenticated owner. The sidecar binds loopback only, so its presence is the trust signal.
        'X-Officer-User': String(ctx.get('user').id),
      },
      body: body.byteLength ? body : undefined,
    });
  } catch (err) {
    console.error('[vpn] headscale sidecar unreachable:', err);
    return ctx.json({ error: 'headscale sidecar unreachable' }, 502);
  }

  return new Response(upstream.body, { status: upstream.status, headers: new Headers(upstream.headers) });
});
