import { Injectable, Logger } from "@nestjs/common";
import {
  HealthCheckError,
  HealthIndicator,
  HealthIndicatorResult,
} from "@nestjs/terminus";
import * as os from "os";

interface SystemHealth {
  memoryHealthy: boolean;
  diskHealthy: boolean;
  cpuHealthy: boolean;
  serviceHealthy: boolean;
}

@Injectable()
export class HealthService extends HealthIndicator {
  private readonly logger = new Logger(HealthService.name);
  private isShuttingDown = false;

  // Thresholds for health checks
  private readonly memoryThreshold = 0.9; // 90% memory usage is considered unhealthy
  private readonly cpuThreshold = 0.95; // 95% CPU usage is considered unhealthy
  private readonly uptimeMinThreshold = 10; // System should be up for at least 10 seconds

  constructor() {
    super();
    process.on("SIGTERM", () => {
      this.logger.log(
        "SIGTERM received, marking service as unhealthy for graceful shutdown",
      );
      this.isShuttingDown = true;
    });
  }

  async isHealthy(): Promise<HealthIndicatorResult> {
    // Check multiple aspects of system health
    const health = await this.checkSystemHealth();

    // Only consider unhealthy if service is shutting down or multiple checks fail
    const isHealthy =
      health.serviceHealthy && (health.memoryHealthy || health.cpuHealthy);

    const result = this.getStatus("service", isHealthy, {
      version: process.env.npm_package_version || "0.0.1",
      timestamp: new Date().toISOString(),
      memoryHealthy: health.memoryHealthy,
      cpuHealthy: health.cpuHealthy,
      diskHealthy: health.diskHealthy,
    });

    if (isHealthy) {
      return result;
    }

    throw new HealthCheckError("Health check failed", result);
  }

  /**
   * Performs multiple health checks on the system
   */
  private async checkSystemHealth(): Promise<SystemHealth> {
    // Check if service is in shutdown state
    const serviceHealthy = !this.isShuttingDown;

    // Check memory usage
    const memoryUsage = process.memoryUsage();
    const totalMemory = os.totalmem();
    const memoryHealthy = memoryUsage.rss / totalMemory < this.memoryThreshold;

    // Check CPU load
    const cpuLoad = os.loadavg()[0] / os.cpus().length;
    const cpuHealthy = cpuLoad < this.cpuThreshold;

    // For now, assume disk is healthy (we don't have direct disk checks here)
    const diskHealthy = true;

    return {
      memoryHealthy,
      cpuHealthy,
      diskHealthy,
      serviceHealthy,
    };
  }

  async checkDependencies(): Promise<HealthIndicatorResult> {
    const isHealthy = true;
    return this.getStatus("dependencies", isHealthy);
  }

  async getMemoryStats(): Promise<HealthIndicatorResult> {
    const memoryUsage = process.memoryUsage();

    return this.getStatus("memory", true, {
      heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024) + "MB",
      heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024) + "MB",
      rss: Math.round(memoryUsage.rss / 1024 / 1024) + "MB",
    });
  }
}
