<?php

declare(strict_types=1);

namespace App\Framework\Http\Streaming;

use App\Framework\Http\Responses\AdaptiveStreamResponse;
use App\Framework\Http\Responses\MediaType;
use App\Framework\Http\Responses\StreamResponse;

class AdaptiveStreamingController
{
    public function manifest(string $videoId): AdaptiveStreamResponse
    {
        // Format basierend auf User-Agent oder Accept-Header erkennen
        $format = $this->detectPreferredFormat();

        return $this->createManifest($videoId, $format);
    }

    public function hlsManifest(string $videoId): AdaptiveStreamResponse
    {
        return $this->createManifest($videoId, StreamingFormat::HLS);
    }

    public function dashManifest(string $videoId): AdaptiveStreamResponse
    {
        return $this->createManifest($videoId, StreamingFormat::DASH);
    }

    public function hlsMediaPlaylist(string $videoId, string $quality): AdaptiveStreamResponse
    {
        $playlist = new AdaptivePlaylist($videoId, PlaylistType::MEDIA);

        // Video-Segmente für diese Qualität laden
        $segments = $this->getVideoSegments($videoId, $quality);

        foreach ($segments as $segment) {
            $playlist->addSegment(
                uri: "segment_{$segment['sequence']}.ts",
                duration: $segment['duration']
            );
        }

        return new AdaptiveStreamResponse(
            playlist: $playlist,
            format: StreamingFormat::HLS
        );
    }

    public function segment(string $videoId, string $quality, string $segment): StreamResponse
    {
        $segmentPath = $this->getSegmentPath($videoId, $quality, $segment);

        if (! file_exists($segmentPath)) {
            throw new \RuntimeException('Segment not found');
        }

        return new StreamResponse(
            filePath: $segmentPath,
            fileSize: filesize($segmentPath),
            mimeType: $this->getSegmentMimeType($segment),
            mediaType: MediaType::VIDEO
        );
    }

    private function createManifest(string $videoId, StreamingFormat $format): AdaptiveStreamResponse
    {
        $playlist = new AdaptivePlaylist($videoId, PlaylistType::MASTER);

        // Standard-Qualitätsstufen
        $playlist
            ->addRepresentation('720p', 2500000, '1280x720', 'avc1.64001f,mp4a.40.2')
            ->addRepresentation('480p', 1500000, '854x480', 'avc1.64001e,mp4a.40.2')
            ->addRepresentation('360p', 800000, '640x360', 'avc1.64001e,mp4a.40.2');

        return new AdaptiveStreamResponse(
            playlist: $playlist,
            format: $format
        );
    }

    private function detectPreferredFormat(): StreamingFormat
    {
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';

        // iOS/Safari bevorzugt HLS
        if (str_contains($userAgent, 'Safari') && str_contains($userAgent, 'Mobile')) {
            return StreamingFormat::HLS;
        }

        // Android/Chrome bevorzugt DASH
        if (str_contains($userAgent, 'Chrome') || str_contains($userAgent, 'Android')) {
            return StreamingFormat::DASH;
        }

        // Accept-Header prüfen
        $accept = $_SERVER['HTTP_ACCEPT'] ?? '';
        if (str_contains($accept, 'application/dash+xml')) {
            return StreamingFormat::DASH;
        }
        if (str_contains($accept, 'application/vnd.apple.mpegurl')) {
            return StreamingFormat::HLS;
        }

        // Default: HLS (breitere Unterstützung)
        return StreamingFormat::HLS;
    }

    private function getVideoSegments(string $videoId, string $quality): array
    {
        // In einer echten Anwendung würden diese aus der Datenbank kommen
        return [
            ['sequence' => 0, 'duration' => 10.0],
            ['sequence' => 1, 'duration' => 10.0],
            ['sequence' => 2, 'duration' => 10.0],
            ['sequence' => 3, 'duration' => 8.5], // Letztes Segment kann kürzer sein
        ];
    }

    private function getSegmentPath(string $videoId, string $quality, string $segment): string
    {
        return "/var/videos/segments/{$videoId}/{$quality}/{$segment}";
    }

    private function getSegmentMimeType(string $segment): string
    {
        if (str_ends_with($segment, '.ts')) {
            return 'video/mp2t'; // MPEG-TS für HLS
        }
        if (str_ends_with($segment, '.mp4')) {
            return 'video/mp4'; // MP4 für DASH
        }

        return 'application/octet-stream';
    }
}
