<?php
declare(strict_types=1);

namespace App\Service\File;

use ApiPlatform\Api\IriConverterInterface;
use ApiPlatform\Api\UrlGeneratorInterface;
use ApiPlatform\Metadata\Get;
use App\ApiResources\Core\File\DownloadRequest;
use App\Entity\Core\File;
use App\Enum\Core\FileHostEnum;
use App\Service\File\Exception\FileNotFoundException;
use App\Service\File\Storage\ApiLegacyStorage;
use App\Service\File\Storage\FileStorageInterface;
use App\Service\File\Storage\LocalStorage;
use Mimey\MimeTypes;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

/**
 * Le gestionnaire de fichiers permet d'effectuer de nombreuses opérations sur les fichiers stockés dans les différents
 * FileStorage (lecture, écriture, suppression...)
 */
class FileManager
{
    public function __construct(
        private LocalStorage $localStorage,
        private ApiLegacyStorage $apiLegacyStorage,
        protected IriConverterInterface $iriConverter
    ) {}

    /**
     * Retourne le storage dans lequel le fichier demandé est supposé se trouver
     * // TODO: voir si ce ne serait pas le boulot d'un ServiceIterator, histoire de rester dans le pattern général
     *
     * @param File $file
     * @return FileStorageInterface
     * @throws FileNotFoundException
     */
    public function getStorageFor(File $file): FileStorageInterface
    {
        if ($file->getHost() === FileHostEnum::API1()->getValue()) {
            return $this->apiLegacyStorage;
        }
        if ($file->getHost() === FileHostEnum::AP2I()->getValue()) {
            return $this->localStorage;
        }
        throw new FileNotFoundException('File ' . $file->getId() . ' was not found (unknown host: ' . $file->getHost() . ')');
    }

    /**
     * Lit le fichier et retourne son contenu
     *
     * @param File $file
     * @return string
     * @throws FileNotFoundException
     */
    public function read(File $file): string
    {
        $storage = $this->getStorageFor($file);
        return $storage->read($file);
    }


    /**
     * Get the IRI to download this file (eg: /api/download/1)
     *
     * @param File $file
     * @return string
     */
    public function getDownloadIri(File $file): string
    {
        return $this->iriConverter->getIriFromResource(
            DownloadRequest::class,
            UrlGeneratorInterface::ABS_PATH,
            new Get(),
            ['fileId' => $file->getId()]
        );
    }

    /**
     * Return the mimetype corresponding to the givent file extension
     *
     * @param string $ext
     * @return string|null
     */
    public static function getMimeTypeFromExt(string $ext): ?string
    {
        return (new MimeTypes)->getMimeType(ltrim($ext, '.'));
    }

    /**
     * Try to guess the mimetype from the filename
     *
     * Return null if it did not manage to guess it.
     *
     * @param string $filename
     * @return string|null
     */
    public static function guessMimeTypeFromFilename(string $filename): ?string
    {
        $ext = pathinfo($filename, PATHINFO_EXTENSION);
        if (empty($ext)) {
            return null;
        }
        return self::getMimeTypeFromExt($ext);
    }
}
