import { Controller, Get, Res } from "@nestjs/common";
import { ApiTags, ApiOperation, ApiResponse } from "@nestjs/swagger";
import type { Response } from "express";
import { Public } from "../../common/decorators";
import { PrismaService } from "../../database/prisma.service";
import { PredictionsService } from "../predictions/predictions.service";

@ApiTags("Health")
@Controller("health")
export class HealthController {
  constructor(
    private prisma: PrismaService,
    private readonly predictionsService: PredictionsService,
  ) {}

  @Get()
  @Public()
  @ApiOperation({ summary: "Basic health check" })
  async check(@Res() response: Response) {
    const database = await this.getDatabaseHealth();
    const aiEngine = await this.predictionsService.checkHealth();
    const ok = database.status === "up" && aiEngine.predictionServiceReady;

    return response.status(ok ? 200 : 503).json({
      status: ok ? "ok" : "degraded",
      timestamp: new Date().toISOString(),
      checks: {
        database,
        aiEngine,
      },
    });
  }

  @Get("ready")
  @Public()
  @ApiOperation({ summary: "Readiness check (includes database)" })
  async readiness(@Res() response: Response) {
    const database = await this.getDatabaseHealth();
    const aiEngine = await this.predictionsService.checkHealth();
    const ready = database.status === "up" && aiEngine.predictionServiceReady;

    return response.status(ready ? 200 : 503).json({
      status: ready ? "ready" : "not_ready",
      timestamp: new Date().toISOString(),
      checks: {
        database,
        aiEngine,
      },
    });
  }

  @Get("live")
  @Public()
  @ApiOperation({ summary: "Liveness check" })
  @ApiResponse({
    status: 200,
    description: "System liveness",
    schema: {
      type: "object",
      properties: {
        status: { type: "string" },
        timestamp: { type: "string" },
      },
    },
  })
  liveness(@Res() response: Response) {
    return response
      .status(200)
      .json({ status: "ok", timestamp: new Date().toISOString() });
  }

  @Get("dependencies")
  @Public()
  @ApiOperation({ summary: "Dependency-level health details" })
  async dependencies(@Res() response: Response) {
    const database = await this.getDatabaseHealth();
    const aiEngine = await this.predictionsService.checkHealth();

    return response.status(200).json({
      timestamp: new Date().toISOString(),
      checks: {
        database,
        aiEngine,
      },
    });
  }

  private async getDatabaseHealth() {
    try {
      await this.prisma.$queryRaw`SELECT 1`;
      return {
        status: "up",
      };
    } catch (error: unknown) {
      return {
        status: "down",
        detail:
          error instanceof Error ? error.message : "Unknown database error",
      };
    }
  }
}
