<?php

declare(strict_types=1);

namespace App\Framework\Health\Checks;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Health\HealthCheckCategory;
use App\Framework\Health\HealthCheckInterface;
use App\Framework\Health\HealthCheckResult;
use App\Framework\Queue\Queue;

final readonly class QueueHealthCheck implements HealthCheckInterface
{
    public function __construct(
        private Queue $queue
    ) {
    }

    public function check(): HealthCheckResult
    {
        $startTime = microtime(true);

        try {
            // Get queue statistics
            $stats = $this->queue->getStats();
            $responseTime = Duration::fromSeconds(microtime(true) - $startTime);

            $queueSize = $stats['total_size'] ?? 0;
            $failedJobs = $stats['failed_jobs'] ?? 0;

            // Determine health based on queue metrics
            $healthy = true;
            $warnings = [];

            // Warning if queue is getting large
            if ($queueSize > 1000) {
                $warnings[] = "Queue size is high ({$queueSize} jobs)";
                $healthy = false;
            }

            // Warning if there are many failed jobs
            if ($failedJobs > 100) {
                $warnings[] = "High number of failed jobs ({$failedJobs})";
                $healthy = false;
            }

            $data = [
                'queue_size' => $queueSize,
                'failed_jobs' => $failedJobs,
                'response_time_ms' => $responseTime->toMilliseconds(),
            ];

            if (!empty($warnings)) {
                return HealthCheckResult::warning(
                    'Queue System',
                    implode(', ', $warnings),
                    $data,
                    $responseTime->toMilliseconds()
                );
            }

            return HealthCheckResult::healthy(
                'Queue System',
                $data,
                $responseTime->toMilliseconds()
            );

        } catch (\Throwable $e) {
            $responseTime = Duration::fromSeconds(microtime(true) - $startTime);

            return HealthCheckResult::unhealthy(
                'Queue System',
                'Queue system failed: ' . $e->getMessage(),
                [
                    'error_type' => get_class($e),
                ],
                $responseTime->toMilliseconds(),
                $e
            );
        }
    }

    public function getName(): string
    {
        return 'Queue System';
    }

    public function getCategory(): HealthCheckCategory
    {
        return HealthCheckCategory::INFRASTRUCTURE;
    }

    public function getTimeout(): int
    {
        return 3000; // 3 seconds
    }
}
