import type { Logger } from "@/observability/logger/types.js";

export interface GracefulShutdownOptions {
  logger: Logger & { flush: () => Promise<void> };
  server: { close: (cb: () => void) => void };
  drainTimeoutMs?: number;
}

const DEFAULT_DRAIN_TIMEOUT_MS = 30_000;

/**
 * Registers a SIGTERM handler that gracefully shuts down the server.
 *
 * On SIGTERM:
 * 1. Stops accepting new requests (server.close)
 * 2. Waits for in-flight requests to drain (up to drainTimeoutMs)
 * 3. Flushes the log buffer
 * 4. Exits with code 0
 *
 * If drain times out, force-exits with code 1.
 *
 * This is a factory function — it does NOT auto-register as middleware.
 * Registration happens in a future integration step.
 */
export function registerGracefulShutdown(
  options: GracefulShutdownOptions,
): void {
  const { logger, server, drainTimeoutMs = DEFAULT_DRAIN_TIMEOUT_MS } =
    options;

  process.on("SIGTERM", () => {
    logger.info("SIGTERM received, starting graceful shutdown", {
      drainTimeoutMs,
    });

    let drained = false;

    // Force-exit timer
    const forceExitTimer = setTimeout(() => {
      if (!drained) {
        logger.error("Drain timeout exceeded, forcing exit", {
          drainTimeoutMs,
        });
        process.exit(1);
      }
    }, drainTimeoutMs);

    // Unref so the timer doesn't keep the process alive if drain succeeds
    if (typeof forceExitTimer === "object" && "unref" in forceExitTimer) {
      forceExitTimer.unref();
    }

    server.close(async () => {
      drained = true;
      clearTimeout(forceExitTimer);

      logger.info("Server closed, flushing logs", undefined);

      try {
        await logger.flush();
      } catch {
        // Best-effort flush — don't block shutdown
      }

      process.exit(0);
    });
  });
}
