<?php

declare(strict_types=1);



class Mime
{
    private const EXT_MAP = [
        'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif',
        'webp' => 'image/webp', 'bmp' => 'image/bmp', 'svg' => 'image/svg+xml', 'avif' => 'image/avif',
        'ico' => 'image/x-icon',
        'mp4' => 'video/mp4', 'm4v' => 'video/mp4', 'webm' => 'video/webm', 'mov' => 'video/quicktime',
        'mkv' => 'video/x-matroska', 'avi' => 'video/x-msvideo', 'flv' => 'video/x-flv', 'ogv' => 'video/ogg',
        'ts' => 'video/mp2t', '3gp' => 'video/3gpp',
        'mp3' => 'audio/mpeg', 'm4a' => 'audio/mp4', 'ogg' => 'audio/ogg', 'wav' => 'audio/wav',
        'pdf' => 'application/pdf', 'zip' => 'application/zip', 'json' => 'application/json',
        'xml' => 'application/xml', 'csv' => 'text/csv', 'txt' => 'text/plain',
    ];

    

    public static function fromFile(string $path, ?string $name = null, string $fallback = 'application/octet-stream'): string
    {
        if ($path !== '' && @is_file($path) && class_exists('finfo')) {
            $m = @(new \finfo(FILEINFO_MIME_TYPE))->file($path);
            if (is_string($m) && $m !== '' && $m !== 'application/octet-stream') {
                return $m;
            }
        }
        if ($path !== '' && @is_file($path)) {
            $head = (string) @file_get_contents($path, false, null, 0, 32);
            $sniff = self::sniff($head);
            if ($sniff !== '') {
                return $sniff;
            }
        }
        $byExt = self::fromExtension($name ?? $path);
        return $byExt !== '' ? $byExt : $fallback;
    }

    

    public static function fromBuffer(string $data, ?string $name = null, string $fallback = 'application/octet-stream'): string
    {
        if ($data !== '' && class_exists('finfo')) {
            $m = @(new \finfo(FILEINFO_MIME_TYPE))->buffer($data);
            if (is_string($m) && $m !== '' && $m !== 'application/octet-stream') {
                return $m;
            }
        }
        $sniff = self::sniff($data);
        if ($sniff !== '') {
            return $sniff;
        }
        $byExt = $name !== null ? self::fromExtension($name) : '';
        return $byExt !== '' ? $byExt : $fallback;
    }

     
    public static function fromExtension(string $nameOrPath): string
    {
        $ext = strtolower(pathinfo($nameOrPath, PATHINFO_EXTENSION));
        return self::EXT_MAP[$ext] ?? '';
    }

     
    private static function sniff(string $head): string
    {
        if ($head === '') {
            return '';
        }
        if (str_starts_with($head, "\xFF\xD8\xFF")) return 'image/jpeg';
        if (str_starts_with($head, "\x89PNG\r\n\x1a\n")) return 'image/png';
        if (str_starts_with($head, 'GIF87a') || str_starts_with($head, 'GIF89a')) return 'image/gif';
        if (str_starts_with($head, 'RIFF') && substr($head, 8, 4) === 'WEBP') return 'image/webp';
        if (str_starts_with($head, 'BM')) return 'image/bmp';
        if (substr($head, 4, 4) === 'ftyp') return 'video/mp4';
        if (str_starts_with($head, "\x1A\x45\xDF\xA3")) return 'video/webm';  
        if (str_starts_with($head, '%PDF-')) return 'application/pdf';
        if (str_starts_with($head, "PK\x03\x04")) return 'application/zip';
        return '';
    }
}
