<?php

declare(strict_types=1);

namespace App\Framework\Http;

use App\Framework\Http\Responses\AdaptiveStreamResponse;
use App\Framework\Http\Responses\SseResponse;
use App\Framework\Http\Responses\StreamResponse;
use App\Framework\Http\Responses\WebSocketResponse;
use App\Framework\Http\Streaming\MimeTypeDetector;
use App\Framework\Http\Streaming\StreamingFormat;

final readonly class ResponseTypeDetector
{
    public function detect(Response $response): ResponseType
    {
        if ($response instanceof SseResponse) {
            return ResponseType::SSE;
        }

        if ($response instanceof WebsocketResponse) {
            return ResponseType::WEBSOCKET;
        }

        if ($response instanceof AdaptiveStreamResponse) {
            return match ($response->format) {
                StreamingFormat::HLS => ResponseType::HLS,
                StreamingFormat::DASH => ResponseType::DASH
            };
        }

        if ($response instanceof StreamResponse) {
            return ResponseType::MEDIA_STREAM;
        }

        return $this->detectFromHeaders($response->headers);
    }

    private function detectFromHeaders(Headers $headers): ResponseType
    {
        if ($this->isSseResponse($headers)) {
            return ResponseType::SSE;
        }

        if ($this->isWebSocketResponse($headers)) {
            return ResponseType::WEBSOCKET;
        }

        $contentType = $headers->getFirst('Content-Type');

        // HLS-Erkennung
        if ($contentType === 'application/vnd.apple.mpegurl' ||
            str_contains($contentType ?? '', 'mpegurl')) {
            return ResponseType::HLS;
        }

        // DASH-Erkennung
        if ($contentType === 'application/dash+xml' ||
            str_contains($contentType ?? '', 'dash+xml')) {
            return ResponseType::DASH;
        }

        if (MimeTypeDetector::isStreamable($contentType ?? '')) {
            return ResponseType::MEDIA_STREAM;
        }

        return ResponseType::HTTP;
    }

    private function isSseResponse(Headers $headers): bool
    {
        $contentType = $headers->getFirst('Content-Type');

        return $contentType === 'text/event-stream' ||
            str_starts_with($contentType ?? '', 'text/event-stream');
    }

    private function isWebSocketResponse(Headers $headers): bool
    {
        $connection = strtolower($headers->getFirst('Connection') ?? '');
        $upgrade = strtolower($headers->getFirst('Upgrade') ?? '');

        return $connection === 'upgrade' && $upgrade === 'websocket';
    }
}
