<?php

declare(strict_types=1);

namespace App\Application\Health;

use App\Framework\Attributes\Route;
use App\Framework\DateTime\Clock;
use App\Framework\Health\HealthCheckCategory;
use App\Framework\Health\HealthCheckManager;
use App\Framework\Http\Method;
use App\Framework\Http\Status;
use App\Framework\Router\Result\JsonResult;

/**
 * Enhanced Health Check Controller with comprehensive monitoring
 *
 * Provides multiple health check endpoints:
 * - /health/detailed - Full health report with all checks
 * - /health/summary - Quick summary of overall health
 * - /health/category/{category} - Health checks by category
 */
final readonly class EnhancedHealthCheckController
{
    public function __construct(
        private HealthCheckManager $healthCheckManager,
        private Clock $clock
    ) {
    }

    /**
     * Detailed health report with all registered health checks
     */
    #[Route(path: '/health/detailed', method: Method::GET)]
    public function detailed(): JsonResult
    {
        $startTime = $this->clock->time();
        $healthReport = $this->healthCheckManager->runAllChecks();

        $checks = [];
        foreach ($healthReport->results as $name => $result) {
            $checks[$name] = [
                'status' => $result->status->value,
                'healthy' => $result->status->isHealthy(),
                'message' => $result->message,
                'response_time_ms' => $result->responseTimeMs,
                'details' => $result->details->toArray(),
            ];

            if ($result->exception !== null) {
                $checks[$name]['error'] = [
                    'type' => get_class($result->exception),
                    'message' => $result->exception->getMessage(),
                ];
            }
        }

        $responseTime = $this->clock->time()->diff($startTime);

        return new JsonResult(
            data: [
                'timestamp' => $this->clock->now()->format('c'),
                'overall_status' => $healthReport->overallStatus->value,
                'overall_healthy' => $healthReport->overallStatus->isHealthy(),
                'checks' => $checks,
                'registered_checks' => $this->healthCheckManager->getRegisteredChecks(),
                'checks_by_category' => $this->healthCheckManager->getChecksByCategory(),
                'response_time_ms' => round($responseTime->toMilliseconds(), 2),
            ],
            status: Status::from($healthReport->overallStatus->isHealthy() ? 200 : 503)
        );
    }

    /**
     * Quick summary of overall health status
     */
    #[Route(path: '/health/summary', method: Method::GET)]
    public function summary(): JsonResult
    {
        $healthReport = $this->healthCheckManager->runAllChecks();

        $healthyCount = 0;
        $warningCount = 0;
        $unhealthyCount = 0;

        foreach ($healthReport->results as $result) {
            match ($result->status->value) {
                'healthy' => $healthyCount++,
                'warning' => $warningCount++,
                'unhealthy' => $unhealthyCount++,
                default => $unhealthyCount++
            };
        }

        return new JsonResult(
            data: [
                'timestamp' => $this->clock->now()->format('c'),
                'overall_status' => $healthReport->overallStatus->value,
                'overall_healthy' => $healthReport->overallStatus->isHealthy(),
                'summary' => [
                    'total_checks' => count($healthReport->results),
                    'healthy' => $healthyCount,
                    'warning' => $warningCount,
                    'unhealthy' => $unhealthyCount,
                ],
            ],
            status: Status::from($healthReport->overallStatus->isHealthy() ? 200 : 503)
        );
    }

    /**
     * Health checks filtered by category
     */
    #[Route(path: '/health/category/{category}', method: Method::GET)]
    public function byCategory(string $category): JsonResult
    {
        // Try to parse category
        $categoryEnum = HealthCheckCategory::tryFrom($category);

        if ($categoryEnum === null) {
            return new JsonResult(
                data: [
                    'error' => "Invalid category: {$category}",
                    'valid_categories' => array_map(
                        fn($cat) => $cat->value,
                        HealthCheckCategory::cases()
                    ),
                ],
                status: Status::BAD_REQUEST
            );
        }

        $healthReport = $this->healthCheckManager->runChecksByCategory($categoryEnum);

        $checks = [];
        foreach ($healthReport->results as $name => $result) {
            $checks[$name] = [
                'status' => $result->status->value,
                'healthy' => $result->status->isHealthy(),
                'message' => $result->message,
                'response_time_ms' => $result->responseTimeMs,
                'details' => $result->details->toArray(),
            ];
        }

        return new JsonResult(
            data: [
                'timestamp' => $this->clock->now()->format('c'),
                'category' => $category,
                'overall_status' => $healthReport->overallStatus->value,
                'overall_healthy' => $healthReport->overallStatus->isHealthy(),
                'checks' => $checks,
            ],
            status: Status::from($healthReport->overallStatus->isHealthy() ? 200 : 503)
        );
    }

    /**
     * Get list of registered health checks
     */
    #[Route(path: '/health/checks', method: Method::GET)]
    public function checks(): JsonResult
    {
        return new JsonResult([
            'timestamp' => $this->clock->now()->format('c'),
            'registered_checks' => $this->healthCheckManager->getRegisteredChecks(),
            'checks_by_category' => $this->healthCheckManager->getChecksByCategory(),
            'total_checks' => count($this->healthCheckManager->getRegisteredChecks()),
        ]);
    }
}
