import type { IncomingMessage, ServerResponse } from 'node:http';
import { toNodeHandler } from 'better-auth/node';
import type { Auth } from '@mosaicstack/auth';
import type { NestFastifyApplication } from '@nestjs/platform-fastify';
import { AUTH } from './auth.tokens.js';

export function mountAuthHandler(app: NestFastifyApplication): void {
  const auth = app.get<Auth>(AUTH);
  const nodeHandler = toNodeHandler(auth);
  const corsOrigin = process.env['GATEWAY_CORS_ORIGIN'] ?? 'http://localhost:3000';

  const fastify = app.getHttpAdapter().getInstance();

  // BetterAuth is mounted at the raw HTTP level via Fastify's onRequest hook,
  // bypassing NestJS middleware (including CORS). We must set CORS headers
  // manually on the raw response before handing off to BetterAuth.
  fastify.addHook(
    'onRequest',
    (
      req: { raw: IncomingMessage; url: string; method: string },
      reply: { raw: ServerResponse; hijack: () => void },
      done: () => void,
    ) => {
      if (!req.url.startsWith('/api/auth/')) {
        done();
        return;
      }

      const origin = req.raw.headers.origin;
      const allowed = corsOrigin.split(',').map((o) => o.trim());

      if (origin && allowed.includes(origin)) {
        reply.raw.setHeader('Access-Control-Allow-Origin', origin);
        reply.raw.setHeader('Access-Control-Allow-Credentials', 'true');
        reply.raw.setHeader(
          'Access-Control-Allow-Methods',
          'GET, POST, PUT, PATCH, DELETE, OPTIONS',
        );
        reply.raw.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Cookie');
      }

      // Handle preflight
      if (req.method === 'OPTIONS') {
        reply.hijack();
        reply.raw.writeHead(204);
        reply.raw.end();
        return;
      }

      reply.hijack();
      nodeHandler(req.raw as IncomingMessage, reply.raw as ServerResponse)
        .then(() => {
          if (!reply.raw.writableEnded) {
            reply.raw.end();
          }
        })
        .catch((err: unknown) => {
          if (!reply.raw.headersSent) {
            reply.raw.writeHead(500, { 'Content-Type': 'application/json' });
          }
          if (!reply.raw.writableEnded) {
            reply.raw.end(JSON.stringify({ error: 'Internal auth error' }));
          }
          console.error('[AUTH] Handler error:', err);
        });
    },
  );
}
