/**
 * Health Service
 * Database, memory, liveness and readiness checks
 * Compatible with erp-core health.service
 *
 * @module Health
 */

import { DataSource } from 'typeorm';

export interface HealthStatus {
  status: 'healthy' | 'unhealthy' | 'degraded';
  timestamp: string;
  version: string;
  uptime: number;
  checks: {
    database: HealthCheck;
    memory: HealthCheck;
  };
}

export interface HealthCheck {
  status: 'up' | 'down';
  responseTime?: number;
  details?: Record<string, unknown>;
}

export class HealthService {
  private startTime: number;

  constructor(private dataSource: DataSource) {
    this.startTime = Date.now();
  }

  async getHealth(): Promise<HealthStatus> {
    const databaseCheck = await this.checkDatabase();
    const memoryCheck = this.checkMemory();

    const isHealthy = databaseCheck.status === 'up' && memoryCheck.status === 'up';
    const isDegraded = databaseCheck.status === 'up' || memoryCheck.status === 'up';

    return {
      status: isHealthy ? 'healthy' : isDegraded ? 'degraded' : 'unhealthy',
      timestamp: new Date().toISOString(),
      version: process.env.APP_VERSION || '1.0.0',
      uptime: Math.floor((Date.now() - this.startTime) / 1000),
      checks: {
        database: databaseCheck,
        memory: memoryCheck,
      },
    };
  }

  async checkDatabase(): Promise<HealthCheck> {
    const startTime = Date.now();
    try {
      if (!this.dataSource.isInitialized) {
        return {
          status: 'down',
          details: { error: 'Database not initialized' },
        };
      }

      await this.dataSource.query('SELECT 1');
      return {
        status: 'up',
        responseTime: Date.now() - startTime,
      };
    } catch (error) {
      return {
        status: 'down',
        responseTime: Date.now() - startTime,
        details: { error: error instanceof Error ? error.message : 'Unknown error' },
      };
    }
  }

  checkMemory(): HealthCheck {
    const memoryUsage = process.memoryUsage();
    const heapUsedPercent = (memoryUsage.heapUsed / memoryUsage.heapTotal) * 100;

    return {
      status: heapUsedPercent < 90 ? 'up' : 'down',
      details: {
        heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024),
        heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024),
        external: Math.round(memoryUsage.external / 1024 / 1024),
        rss: Math.round(memoryUsage.rss / 1024 / 1024),
        heapUsedPercent: Math.round(heapUsedPercent * 100) / 100,
      },
    };
  }

  async getLiveness(): Promise<{ status: 'ok' }> {
    return { status: 'ok' };
  }

  async getReadiness(): Promise<{ status: 'ready' | 'not_ready'; details?: Record<string, unknown> }> {
    const databaseCheck = await this.checkDatabase();
    if (databaseCheck.status !== 'up') {
      return {
        status: 'not_ready',
        details: { database: databaseCheck },
      };
    }
    return { status: 'ready' };
  }
}
