<?php

    declare(strict_types = 1);
    error_reporting(E_ALL & ~E_NOTICE);

    /*────────────────────── Настройки ──────────────────────*/
    const MAX_DIM        = 2000;          // предел по сторонам
    const DEFAULT_Q      = 8;             // q=… по умолчанию (0-9)
    const CACHE_LIFETIME = 31_104_000;    // 1 год в секундах

    /*─────────────────── Вспом-функции ─────────────────────*/
    function accepts(string $mime) : bool {
        return str_contains($_SERVER['HTTP_ACCEPT'] ?? '', $mime);
    }

    function canEncodeAvif() : bool {
        return function_exists('imageavif')
            || (class_exists(Imagick::class)
                && in_array('AVIF', Imagick::queryFormats(), true));
    }

    function wantAvif() : bool { return accepts('image/avif') && canEncodeAvif(); }

    function wantWebp() : bool { return accepts('image/webp') && function_exists('imagewebp'); }

    /*──────────────────── Входные данные ───────────────────*/
    $q      = isset($_GET['q']) && is_numeric($_GET['q']) && (int)$_GET['q'] <= 9 ? (int)$_GET['q'] : DEFAULT_Q;
    $w      = isset($_GET['w']) ? min((int)$_GET['w'], MAX_DIM) : null;
    $h      = isset($_GET['h']) ? min((int)$_GET['h'], MAX_DIM) : null;
    $rotate = isset($_GET['rotate']) ? (int)$_GET['rotate'] : null;

    if (empty($_GET['thumb'])) {
        exit;
    }

    /* ─── префикс <WxH>/ в thumb ─── */
    $parts = explode('/', $_GET['thumb']);
    if (str_contains($parts[0], 'x') && count($parts) > 1) {
        [
            $w,
            $h,
        ]
            = array_map('intval', explode('x', $parts[0]));
        array_shift($parts);
        $_GET['thumb'] = implode('/', $parts);
    }

    /*───────────────── Исходный файл ───────────────────────*/
    $src = __DIR__ . '/images/' . $_GET['thumb'];
    if ( !is_file($src)) {
        $src = __DIR__ . '/images/default.png';
    }

    [
        $srcW,
        $srcH,
        $srcType,
    ]
        = getimagesize($src) ? : [
        0,
        0,
        0,
    ];

    if ( !in_array($srcType, [
        IMAGETYPE_GIF,
        IMAGETYPE_JPEG,
        IMAGETYPE_PNG,
        IMAGETYPE_WEBP,
        IMAGETYPE_AVIF,
    ], true)) {
        http_response_code(400);
        exit;
    }

    /*──────────────────── Формат вывода ───────────────────*/
    $useAvif = wantAvif();
    $useWebp = !$useAvif && wantWebp();
    $mime    = $useAvif ? 'image/avif' : ($useWebp ? 'image/webp' : image_type_to_mime_type($srcType));

    /*──────────────────── Кеширование ─────────────────────*/
    $env          = parse_ini_file(__DIR__ . '/.env') ? : [];
    $cacheEnabled = (bool)($env['IMAGE_CACHE'] ?? false);
    $cacheFile    = '';

    if ($cacheEnabled && ($useAvif || $useWebp)) {
        $ext       = $useAvif ? 'avif' : 'webp';
        $sizeDir   = ($w ?? '_') . 'x' . ($h ?? '_');
        $rotDir    = $rotate ? $rotate . '/' : '';
        $cacheDir  = __DIR__ . "/images/cache/$sizeDir/$rotDir";
        $baseName  = pathinfo($_GET['thumb'], PATHINFO_FILENAME);
        $cacheFile = "$cacheDir$baseName.$ext";

        if (is_file($cacheFile)) {
            header("Content-Type: $mime");
            header('Expires: ' . gmdate('D, d M Y H:i:s', time() + CACHE_LIFETIME) . ' GMT');
            header("Cache-Control: max-age=" . CACHE_LIFETIME . ', public');
            readfile($cacheFile);
            exit;
        }
    }

    /*────────────────── Загрузка исходника ────────────────*/
    $srcImg = match ($srcType) {
        IMAGETYPE_GIF => imagecreatefromgif($src),
        IMAGETYPE_JPEG => imagecreatefromjpeg($src),
        IMAGETYPE_PNG => imagecreatefrompng($src),
        IMAGETYPE_WEBP => imagecreatefromwebp($src),
        IMAGETYPE_AVIF => imagecreatefromavif($src),
    };

    /*────────────────── Масштабирование ───────────────────*/
//    $w      ??= $srcW;
//    $h      ??= $srcH;
//    $ratio  = min($w / $srcW, $h / $srcH);
//    $dstW   = (int)round($srcW * $ratio);
//    $dstH   = (int)round($srcH * $ratio);
//    $canvas = imagecreatetruecolor($w, $h);
//    imagealphablending($canvas, false);
//    imagesavealpha($canvas, true);
//    imagefill($canvas, 0, 0, IMG_COLOR_TRANSPARENT);
//    imagecopyresampled($canvas, $srcImg, (int)(($w - $dstW) / 2), (int)(($h - $dstH) / 2), 0, 0, $dstW, $dstH, $srcW, $srcH);

    if ($w && !$h) {
        // только ширина, высоту считаем пропорционально
        $ratio = $w / $srcW;
        $dstW  = $w;
        $dstH  = (int)round($srcH * $ratio);
    } elseif (!$w && $h) {
        // только высота, ширину считаем пропорционально
        $ratio = $h / $srcH;
        $dstW  = (int)round($srcW * $ratio);
        $dstH  = $h;
    } elseif ($w && $h) {
        // вписываем в прямоугольник $w x $h с сохранением пропорций (выдает не пустоты, а реальный размер)
        $ratio = min($w / $srcW, $h / $srcH);
        $dstW  = (int)round($srcW * $ratio);
        $dstH  = (int)round($srcH * $ratio);
    } else {
        $dstW = $srcW;
        $dstH = $srcH;
    }

    $canvas = imagecreatetruecolor($dstW, $dstH);
    imagealphablending($canvas, false);
    imagesavealpha($canvas, true);
    imagefill($canvas, 0, 0, IMG_COLOR_TRANSPARENT);
    imagecopyresampled($canvas, $srcImg, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);
    imagedestroy($srcImg);

    if ($rotate) {
        $canvas = imagerotate($canvas, min($rotate, 360), 0);
    }

    /*────────────────── Заголовки HTTP ───────────────────*/
    header("Content-Type: $mime");
    $lastMod = filemtime($src);
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastMod) . ' GMT');
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + CACHE_LIFETIME) . ' GMT');
    header("Cache-Control: max-age=" . CACHE_LIFETIME . ', public');

    /*────────────────── Вывод и сохранение ───────────────*/
    $qualityWebp = $qualityJpeg = $q * 8;
    $qualityAvif = $q * 9;
    $qualityPng  = $q;

    $save = static function(?string $path) use (
        $canvas, $useAvif, $useWebp, $srcType, $qualityAvif, $qualityWebp, $qualityJpeg, $qualityPng,
    ) {
        return $useAvif ? imageavif($canvas, $path, $qualityAvif) : ($useWebp ? imagewebp($canvas, $path, $qualityWebp) : ($srcType
        === IMAGETYPE_PNG ? imagepng($canvas, $path, $qualityPng) : imagejpeg($canvas, $path, $qualityJpeg)));
    };

    $save(null);                         // вывод в буфер

    if ($cacheFile) {                    // сохранение в кеш
        if ( !is_dir(dirname($cacheFile))) {
            mkdir(dirname($cacheFile), 0775, true);
        }
        $save($cacheFile);
    }

    imagedestroy($canvas);