/**
 * Health check routes for SentryAgent.ai AgentIdP.
 *
 * GET /health          — quick liveness check (existing)
 * GET /health/detailed — full dependency health with latency (task 2.4)
 *
 * Both endpoints are unauthenticated — safe to call from monitoring systems.
 */

import { Router, Request, Response } from 'express';
import { Pool } from 'pg';
import { RedisClientType } from 'redis';
import { DbProbe, HealthDetailedController } from '../controllers/HealthDetailedController.js';

/** Response shape for GET /health */
interface HealthResponse {
  status: 'ok' | 'degraded';
  version: string;
  uptime: number;
  services: {
    postgres: 'connected' | 'disconnected';
    redis: 'connected' | 'disconnected';
  };
}

/**
 * Creates and returns the Express router for health endpoints.
 *
 * @param pool  - PostgreSQL connection pool.
 * @param redis - Redis client instance.
 * @returns Configured Express router.
 */
export function createHealthRouter(pool: Pool, redis: RedisClientType): Router {
  const router = Router();

  // Create a minimal DbProbe adapter — keeps raw Pool out of the controller.
  const dbProbe: DbProbe = {
    async checkLiveness(): Promise<void> {
      const client = await pool.connect();
      try {
        await client.query('SELECT 1');
      } finally {
        client.release();
      }
    },
  };

  // Instantiate the detailed health controller with optional service clients.
  const detailedController = new HealthDetailedController({
    dbProbe,
    redisClient: redis,
    vaultAddr: process.env['VAULT_ADDR'] ?? undefined,
    opaUrl: process.env['OPA_URL'] ?? undefined,
  });

  /**
   * GET /health
   * Returns 200 when all services are healthy, 503 when any are degraded.
   */
  router.get('/', (_req: Request, res: Response): void => {
    const check = async (): Promise<void> => {
      let postgresStatus: 'connected' | 'disconnected' = 'disconnected';
      let redisStatus: 'connected' | 'disconnected' = 'disconnected';

      // Check PostgreSQL
      try {
        const client = await pool.connect();
        await client.query('SELECT 1');
        client.release();
        postgresStatus = 'connected';
      } catch {
        postgresStatus = 'disconnected';
      }

      // Check Redis
      try {
        await redis.ping();
        redisStatus = 'connected';
      } catch {
        redisStatus = 'disconnected';
      }

      const allHealthy = postgresStatus === 'connected' && redisStatus === 'connected';
      const httpStatus = allHealthy ? 200 : 503;

      const body: HealthResponse = {
        status: allHealthy ? 'ok' : 'degraded',
        version: process.env['npm_package_version'] ?? '1.0.0',
        uptime: Math.floor(process.uptime()),
        services: {
          postgres: postgresStatus,
          redis: redisStatus,
        },
      };

      res.status(httpStatus).json(body);
    };

    void check();
  });

  /**
   * GET /health/detailed
   * Returns per-service health with latency.
   * 200 = all healthy, 207 = any degraded, 503 = any unreachable.
   */
  router.get('/detailed', detailedController.handle);

  return router;
}
