import { createServer } from '../server/api.js';
import { logger, flushLoggerSync } from '../core/logger.js';
import { cliErrorKey } from './cli-message.js';
import { isWalCorruptionError, WAL_RECOVERY_SUGGESTION } from '../core/lbug/lbug-config.js';

// Catch anything that would cause a silent exit. Pino v10's default
// destination is `sync: false` (SonicBoom buffered) — call
// `flushLoggerSync()` between the log and `process.exit(1)` so the crash
// record is not lost to the unflushed buffer. Worker-thread transports
// (pino-pretty under TTY) handle their own flush on process exit in v10,
// so no separate `pino.final` integration is needed (the API was removed
// in v10 because the transport architecture made it unnecessary).
//
// We pass the Error itself in `{ err }` so pino's built-in err serializer
// captures `type`, `message`, and `stack` as structured fields.
process.on('uncaughtException', (err) => {
  logger.error({ err }, '[gitnexus serve] Uncaught exception');
  flushLoggerSync();
  process.exit(1);
});
process.on('unhandledRejection', (reason) => {
  const err = reason instanceof Error ? reason : new Error(String(reason));
  logger.error({ err }, '[gitnexus serve] Unhandled rejection');
  flushLoggerSync();
  process.exit(1);
});

export const serveCommand = async (options?: { port?: string; host?: string }) => {
  const port = Number(options?.port ?? 4747);
  // Default to 'localhost' so the OS decides whether to bind to 127.0.0.1 or
  // ::1 based on system configuration, avoiding spurious CORS errors when the
  // hosted frontend at gitnexus.vercel.app connects to localhost.
  const host = options?.host ?? 'localhost';

  try {
    await createServer(port, host);
  } catch (err: any) {
    if (isWalCorruptionError(err)) {
      cliErrorKey(
        'serve.walCorruption',
        { suggestion: WAL_RECOVERY_SUGGESTION },
        { recoveryHint: 'wal-corruption' },
      );
    } else if (err.code === 'EADDRINUSE') {
      cliErrorKey(
        'serve.portInUse',
        { message: String(err.message || err), port },
        { code: err.code, port, host },
      );
    } else {
      cliErrorKey(
        'serve.startFailed',
        { message: String(err.message || err) },
        { code: err.code, port, host },
      );
    }
    if (err.stack && process.env.DEBUG) {
      logger.debug({ stack: err.stack }, 'serve start error stack');
    }
    flushLoggerSync();
    process.exit(1);
  }
};
