<?php

declare(strict_types=1);

namespace App\Framework\Http;

final class MimeTypeResolver
{
    /** @var array<string, MimeType> */
    private const EXTENSION_MAP = [
        // Text
        'txt' => MimeType::TEXT_PLAIN,
        'html' => MimeType::TEXT_HTML,
        'htm' => MimeType::TEXT_HTML,
        'css' => MimeType::TEXT_CSS,
        'csv' => MimeType::TEXT_CSV,
        'js' => MimeType::TEXT_JAVASCRIPT,
        'xml' => MimeType::TEXT_XML,
        'md' => MimeType::TEXT_MARKDOWN,
        'markdown' => MimeType::TEXT_MARKDOWN,

        // Application
        'json' => MimeType::APPLICATION_JSON,
        'pdf' => MimeType::APPLICATION_PDF,
        'zip' => MimeType::APPLICATION_ZIP,
        'gz' => MimeType::APPLICATION_GZIP,
        'gzip' => MimeType::APPLICATION_GZIP,
        'rar' => MimeType::APPLICATION_RAR,
        '7z' => MimeType::APPLICATION_7Z,
        'doc' => MimeType::APPLICATION_MSWORD,
        'docx' => MimeType::APPLICATION_MSWORD_X,
        'xls' => MimeType::APPLICATION_EXCEL,
        'xlsx' => MimeType::APPLICATION_EXCEL_X,
        'ppt' => MimeType::APPLICATION_POWERPOINT,
        'pptx' => MimeType::APPLICATION_POWERPOINT_X,

        // Images
        'jpg' => MimeType::IMAGE_JPEG,
        'jpeg' => MimeType::IMAGE_JPEG,
        'png' => MimeType::IMAGE_PNG,
        'gif' => MimeType::IMAGE_GIF,
        'svg' => MimeType::IMAGE_SVG,
        'webp' => MimeType::IMAGE_WEBP,
        'bmp' => MimeType::IMAGE_BMP,
        'tiff' => MimeType::IMAGE_TIFF,
        'tif' => MimeType::IMAGE_TIFF,
        'ico' => MimeType::IMAGE_ICO,

        // Audio
        'mp3' => MimeType::AUDIO_MPEG,
        'wav' => MimeType::AUDIO_WAV,
        'ogg' => MimeType::AUDIO_OGG,
        'aac' => MimeType::AUDIO_AAC,
        'flac' => MimeType::AUDIO_FLAC,

        // Video
        'mp4' => MimeType::VIDEO_MP4,
        'webm' => MimeType::VIDEO_WEBM,
        'avi' => MimeType::VIDEO_AVI,
        'mov' => MimeType::VIDEO_QUICKTIME,

        // Fonts
        'woff' => MimeType::FONT_WOFF,
        'woff2' => MimeType::FONT_WOFF2,
        'ttf' => MimeType::FONT_TTF,
        'otf' => MimeType::FONT_OTF,
    ];

    /** @var array<string, array<int, string>> */
    private const MIME_TYPE_EXTENSIONS = [
        MimeType::TEXT_PLAIN->value => ['txt'],
        MimeType::TEXT_HTML->value => ['html', 'htm'],
        MimeType::TEXT_CSS->value => ['css'],
        MimeType::TEXT_CSV->value => ['csv'],
        MimeType::TEXT_JAVASCRIPT->value => ['js'],
        MimeType::TEXT_XML->value => ['xml'],
        MimeType::TEXT_MARKDOWN->value => ['md', 'markdown'],

        MimeType::APPLICATION_JSON->value => ['json'],
        MimeType::APPLICATION_PDF->value => ['pdf'],
        MimeType::APPLICATION_ZIP->value => ['zip'],
        MimeType::APPLICATION_GZIP->value => ['gz', 'gzip'],
        MimeType::APPLICATION_RAR->value => ['rar'],
        MimeType::APPLICATION_7Z->value => ['7z'],
        MimeType::APPLICATION_MSWORD->value => ['doc'],
        MimeType::APPLICATION_MSWORD_X->value => ['docx'],
        MimeType::APPLICATION_EXCEL->value => ['xls'],
        MimeType::APPLICATION_EXCEL_X->value => ['xlsx'],
        MimeType::APPLICATION_POWERPOINT->value => ['ppt'],
        MimeType::APPLICATION_POWERPOINT_X->value => ['pptx'],

        MimeType::IMAGE_JPEG->value => ['jpg', 'jpeg'],
        MimeType::IMAGE_PNG->value => ['png'],
        MimeType::IMAGE_GIF->value => ['gif'],
        MimeType::IMAGE_SVG->value => ['svg'],
        MimeType::IMAGE_WEBP->value => ['webp'],
        MimeType::IMAGE_BMP->value => ['bmp'],
        MimeType::IMAGE_TIFF->value => ['tiff', 'tif'],
        MimeType::IMAGE_ICO->value => ['ico'],

        MimeType::AUDIO_MPEG->value => ['mp3'],
        MimeType::AUDIO_WAV->value => ['wav'],
        MimeType::AUDIO_OGG->value => ['ogg'],
        MimeType::AUDIO_AAC->value => ['aac'],
        MimeType::AUDIO_FLAC->value => ['flac'],

        MimeType::VIDEO_MP4->value => ['mp4'],
        MimeType::VIDEO_WEBM->value => ['webm'],
        MimeType::VIDEO_AVI->value => ['avi'],
        MimeType::VIDEO_QUICKTIME->value => ['mov'],

        MimeType::FONT_WOFF->value => ['woff'],
        MimeType::FONT_WOFF2->value => ['woff2'],
        MimeType::FONT_TTF->value => ['ttf'],
        MimeType::FONT_OTF->value => ['otf'],
    ];

    public static function fromExtension(string $extension): ?MimeType
    {
        $extension = strtolower(ltrim($extension, '.'));

        return self::EXTENSION_MAP[$extension] ?? null;
    }

    public static function fromFilePath(string $filePath): ?MimeType
    {
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);

        return self::fromExtension($extension);
    }

    /**
     * @return array<int, string>
     */
    public static function getExtensions(MimeType $mimeType): array
    {
        return self::MIME_TYPE_EXTENSIONS[$mimeType->value] ?? [];
    }

    public static function getPreferredExtension(MimeType $mimeType): ?string
    {
        $extensions = self::getExtensions($mimeType);

        return $extensions[0] ?? null;
    }

    public static function fromString(string $mimeTypeString): ?MimeType
    {
        foreach (MimeType::cases() as $case) {
            if ($case->value === $mimeTypeString) {
                return $case;
            }
        }

        return null;
    }
}
