<?php

declare(strict_types=1);

namespace App\Application\Metrics;

use App\Framework\Attributes\Route;
use App\Framework\Http\Headers;
use App\Framework\Http\HttpResponse;
use App\Framework\Http\Method;
use App\Framework\Http\Request;
use App\Framework\Http\Status;
use App\Framework\Metrics\Formatters\JsonFormatter;
use App\Framework\Metrics\Formatters\MetricsFormatter;
use App\Framework\Metrics\Formatters\OpenMetricsFormatter;
use App\Framework\Metrics\Formatters\PrometheusFormatter;
use App\Framework\Metrics\Formatters\StatsDFormatter;
use App\Framework\Metrics\MetricsCollector;

/**
 * Controller for exposing application metrics in various formats
 */
final readonly class MetricsController
{
    /**
     * @var array<string, MetricsFormatter>
     */
    private array $formatters;

    public function __construct(
        private MetricsCollector $collector
    ) {
        $this->formatters = [
            'prometheus' => new PrometheusFormatter(),
            'openmetrics' => new OpenMetricsFormatter(),
            'json' => new JsonFormatter(prettyPrint: false),
            'json-pretty' => new JsonFormatter(prettyPrint: true),
            'statsd' => new StatsDFormatter(),
        ];
    }

    #[Route(path: '/metrics', method: Method::GET)]
    public function metrics(Request $request): HttpResponse
    {
        // Determine format from query parameter or Accept header
        $format = $this->determineFormat($request);

        // Get the appropriate formatter
        $formatter = $this->formatters[$format] ?? $this->formatters['prometheus'];

        // Collect metrics
        $metrics = $this->collector->collect();

        // Format and return
        return new HttpResponse(
            status: Status::OK,
            headers: new Headers([
                'Content-Type' => $formatter->getContentType(),
                'Cache-Control' => 'no-cache, no-store, must-revalidate',
            ]),
            body: $formatter->format($metrics)
        );
    }

    #[Route(path: '/metrics/health', method: Method::GET)]
    public function health(Request $request): HttpResponse
    {
        // Simple health check that confirms metrics system is working
        $formatter = new JsonFormatter(prettyPrint: true);
        $metrics = $this->collector->collect();

        $health = [
            'status' => 'healthy',
            'metrics_count' => count($metrics->getAllMetrics()),
            'timestamp' => $metrics->getCollectedAt()?->toIso8601(),
        ];

        return new HttpResponse(
            status: Status::OK,
            headers: new Headers([
                'Content-Type' => 'application/json',
                'Cache-Control' => 'no-cache',
            ]),
            body: json_encode($health, JSON_PRETTY_PRINT) ?: '{"error":"Encoding failed"}'
        );
    }

    private function determineFormat(Request $request): string
    {
        // Check query parameter first
        $queryFormat = $request->queryParams['format'] ?? null;
        if ($queryFormat !== null && isset($this->formatters[$queryFormat])) {
            return $queryFormat;
        }

        // Check Accept header
        $acceptHeader = $request->headers->getFirst('Accept') ?? 'text/plain';

        // Map Accept headers to formats
        return match(true) {
            str_contains($acceptHeader, 'application/openmetrics-text') => 'openmetrics',
            str_contains($acceptHeader, 'application/json') => 'json',
            str_contains($acceptHeader, 'text/plain') => 'prometheus',
            default => 'prometheus',
        };
    }
}
