<?php

declare(strict_types=1);

namespace App\Domain\Media;

use App\Framework\Ulid\StringConverter;
use App\Framework\Ulid\Ulid;

final readonly class ImageResizer
{
    public function __construct()
    {
    }

    public function __invoke(
        Image $image,
        int $maxWidth,
        int $maxHeight,
        int $quality = 9
    ): ImageVariant {
        $sourcePath = $image->path->join($image->filename)->toString();

        $filename = str_replace('original', 'thumbnail', $image->filename);

        $destination = $image->path->join($filename)->toString();

        $imageInfo = getimagesize($sourcePath);

        if ($imageInfo === false) {
            throw new \RuntimeException('Could not get image info');
        }

        $imageType = $imageInfo[2];

        $source = $this->createImageFromFile($sourcePath, $imageType);

        $orignalWidth = imagesx($source);
        $orignalHeight = imagesy($source);

        $scale = min($maxWidth / $orignalWidth, $maxHeight / $orignalHeight);

        $newWidth = (int)round($orignalWidth * $scale);
        $newHeight = (int)round($orignalHeight * $scale);

        #$src = imagecreatefrompng($sourcePath);
        $dst = imagecreatetruecolor($newWidth, $newHeight);

        imagecopyresampled($dst, $source, 0, 0, 0, 0, $newWidth, $newHeight, $orignalWidth, $orignalHeight);

        $this->saveImage($dst, $destination, $imageType, $quality);

        imagedestroy($source);
        imagedestroy($dst);

        $fileSize = filesize($destination);

        // ULID mit StringConverter in binäres Format konvertieren
        $binaryImageId = $image->ulid;


        return new ImageVariant(
            imageId    : $binaryImageId,
            variantType: 'thumbnail',
            format     : '',
            mimeType   : $image->mimeType,
            fileSize   : $fileSize,
            width      : $newWidth,
            height     : $newHeight,
            filename   : $filename,
            path: $image->path->toString(),
        );
    }

    private function createImageFromFile(string $sourcePath, mixed $imageType): \GdImage
    {
        return match ($imageType) {
            IMAGETYPE_PNG => imagecreatefrompng($sourcePath),
            IMAGETYPE_JPEG => imagecreatefromjpeg($sourcePath),
            IMAGETYPE_GIF => imagecreatefromgif($sourcePath),
            IMAGETYPE_WEBP => imagecreatefromwebp($sourcePath),
            default => throw new \RuntimeException('Unsupported image type'),
        };
    }

    private function saveImage($image, string $destination, int $imageType, int $quality): void
    {
        match ($imageType) {
            IMAGETYPE_JPEG => imagejpeg($image, $destination, $quality),
            IMAGETYPE_PNG => imagepng($image, $destination, (int)round(9 - ($quality * 9 / 100))),
            IMAGETYPE_GIF => imagegif($image, $destination),
            IMAGETYPE_WEBP => imagewebp($image, $destination, $quality),
            default => throw new \RuntimeException('Unsupported image type'),
        };
    }
}
