import { Controller, Get, Inject, Logger } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ConfigService } from '@nestjs/config';
import { KNEX_CONNECTION } from '../../database/database.module';
import type Knex from 'knex';

interface HealthCheckResult {
  status: 'ok' | 'error';
  timestamp: string;
  uptime: number;
  version: string;
  services: {
    database: { status: string; latency?: number };
  };
}

@ApiTags('Health')
@Controller('health')
export class HealthController {
  private readonly logger = new Logger(HealthController.name);

  constructor(
    @Inject(KNEX_CONNECTION) private readonly knex: Knex.Knex,
    private readonly configService: ConfigService,
  ) {}

  @Get()
  @ApiOperation({
    summary: 'Basic health check',
    description: 'Returns basic service health status',
  })
  @ApiResponse({ status: 200, description: 'Service is healthy' })
  async check(): Promise<HealthCheckResult> {
    const dbHealth = await this.checkDatabase();

    const overallStatus = dbHealth.status === 'up' ? 'ok' : 'error';

    return {
      status: overallStatus,
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      version: '1.0.0',
      services: {
        database: dbHealth,
      },
    };
  }

  @Get('ready')
  @ApiOperation({
    summary: 'Readiness check',
    description: 'Returns whether the service is ready to accept traffic',
  })
  @ApiResponse({ status: 200, description: 'Service is ready' })
  async readiness() {
    const dbHealth = await this.checkDatabase();

    return {
      ready: dbHealth.status === 'up',
      timestamp: new Date().toISOString(),
      checks: {
        database: dbHealth,
      },
    };
  }

  @Get('live')
  @ApiOperation({
    summary: 'Liveness check',
    description: 'Returns whether the service process is alive',
  })
  @ApiResponse({ status: 200, description: 'Service is alive' })
  async liveness() {
    return {
      alive: true,
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      memory: process.memoryUsage(),
    };
  }

  private async checkDatabase(): Promise<{ status: string; latency?: number }> {
    try {
      const start = Date.now();
      await this.knex.raw('SELECT 1');
      const latency = Date.now() - start;
      return { status: 'up', latency };
    } catch (error) {
      this.logger.error('Database health check failed', error);
      return { status: 'down' };
    }
  }
}
