<?php

declare(strict_types=1);

namespace App\Administration\Application\Service;

use App\Administration\Application\Port\ImageProcessor;
use App\Administration\Application\Port\LogoStorage;
use App\Administration\Domain\Exception\LogoFormatInvalideException;
use App\Administration\Domain\Exception\LogoTropGrosException;
use App\Administration\Domain\Model\SchoolBranding\LogoUrl;
use App\Shared\Domain\Tenant\TenantId;

use function bin2hex;
use function in_array;
use function random_bytes;
use function strpos;
use function substr;

use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * Service applicatif pour l'upload et le traitement des logos.
 *
 * Responsabilités :
 * - Validation du fichier (type MIME, taille)
 * - Redimensionnement via port ImageProcessor (max 200x200px)
 * - Stockage via port LogoStorage
 * - Suppression des anciens fichiers lors du remplacement
 */
final readonly class LogoUploader
{
    private const int MAX_SIZE = 2 * 1024 * 1024; // 2 Mo
    private const int MAX_DIMENSION = 200;
    /** @var string[] */
    private const array ALLOWED_TYPES = ['image/png', 'image/jpeg'];
    private const string KEY_PREFIX = 'logos/';

    public function __construct(
        private LogoStorage $storage,
        private ImageProcessor $imageProcessor,
    ) {
    }

    public function upload(UploadedFile $file, TenantId $tenantId, ?LogoUrl $oldLogoUrl = null): LogoUrl
    {
        $this->validerFichier($file);

        $content = $this->imageProcessor->resize(
            $file->getPathname(),
            self::MAX_DIMENSION,
            self::MAX_DIMENSION,
        );

        $key = self::KEY_PREFIX . $tenantId . '/' . bin2hex(random_bytes(8)) . '.png';
        $url = $this->storage->store($content, $key, 'image/png');

        if ($oldLogoUrl !== null) {
            $this->deleteByUrl($oldLogoUrl);
        }

        return new LogoUrl($url);
    }

    public function deleteByUrl(LogoUrl $logoUrl): void
    {
        $url = $logoUrl->value;
        $pos = strpos($url, self::KEY_PREFIX);

        if ($pos !== false) {
            $this->storage->delete(substr($url, $pos));
        }
    }

    private function validerFichier(UploadedFile $file): void
    {
        $size = $file->getSize();
        if ($size > self::MAX_SIZE) {
            throw LogoTropGrosException::pourTaille($size, self::MAX_SIZE);
        }

        $mimeType = $file->getMimeType() ?? 'unknown';
        if (!in_array($mimeType, self::ALLOWED_TYPES, true)) {
            throw LogoFormatInvalideException::pourType($mimeType, self::ALLOWED_TYPES);
        }
    }
}
