<?php

namespace AutoAdmin\Bundle\Media\Upload;

use AutoAdmin\Bundle\Content\Site\SiteContextHelper;
use AutoAdmin\Bundle\Core\Upload\FileVerifier;
use AutoAdmin\Bundle\Media\Helper\FileHelper;
use AutoAdmin\Bundle\Media\Library\MediaTypeResolver;
use AutoAdmin\Bundle\Media\Library\MediaPathGenerator;
use AutoAdmin\Bundle\Media\Model\Library\FileMediaInterface;
use AutoAdmin\Bundle\Media\Model\Library\FileMediaTranslationInterface;
use AutoAdmin\Bundle\Media\Model\Library\ImageMediaInterface;
use AutoAdmin\Bundle\Media\Namer\MediaNamer;
use Exception;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class MediaUploadHandler
{
    public function __construct(
        protected MediaNamer $namer,
        protected FileSystem $fileSystem,
        protected SiteContextHelper $siteContext,
        protected string $projectDir,
        protected MediaTypeResolver $typeResolver,
        protected MediaPathGenerator $mediaUrlGenerator,
        protected FileVerifier $verifier,
    ) {
    }

    public function handle(FileMediaInterface $media): bool
    {
        $file = $media->getFile();
        if (null === $file) {
            return false;
        }

        $this->verifier->verify($file);

        /** @var FileMediaTranslationInterface $mediaTrans */
        $mediaTrans = $media->getCurrentTranslation();

        if ($file instanceof UploadedFile) {
            if (
                $media->getId() &&
                $file->getClientOriginalName() !== $media->getOriginalName()
            ) {
                // replacing file
                $this->handleRemove($media);
            }

            // replacement
            if ($media->getId() && $media->getOriginalName()) {
                $this->handleRemove($media, true);
            }

            $media->setOriginalName($file->getClientOriginalName());
            $media->setMimeType($file->getMimeType());
            $media->setSize($file->getSize());

            if ($media instanceof ImageMediaInterface) {
                try {
                    $size = getimagesize($file->getPathname());
                    if (!$size) {
                        $size = [0, 0];
                    }
                } catch (Exception $e) {
                    $size = [0, 0];
                }

                $media->setWidth($size[0]);
                $media->setHeight($size[1]);
            }

            $mediaTrans->setFileName($this->namer->generateName($media->getOriginalName()));
            $media->setExtension(FileHelper::extractExtension($media->getOriginalName()));

            $file->move($this->getUploadPath($media), $mediaTrans->getFileName());
        } elseif ($file instanceof File) {
            // used to programmatically create media (without real uploads)
            $src = $file->getPathname();
            $dest = $this->getUploadPath($media).'/'.$file->getFilename();

            // replacement
            if ($media->getId() && $media->getOriginalName()) {
                $this->handleRemove($media);
            }

            $this->fileSystem->copy($src, $dest);

            $media->setOriginalName($file->getFilename());
            $media->setMimeType($file->getMimeType());
            $media->setSize($file->getSize());
            $media->setFile(null);
            $mediaTrans->setTitle($file->getFilename());
            $mediaTrans->setFileName($file->getFilename());
        }

        return true;
    }

    public function handleRemove(FileMediaInterface $media)
    {
        if (
            empty($media->getCurrentTranslation()->getFileName())
            && empty($media->getOriginalName())
        ) {
            return;
        }

        $uploadPath = $this->getUploadPath($media);
        $filePaths = [
            $uploadPath.'/'.$media->getCurrentTranslation()->getFileName(),
            $uploadPath.'/'.$media->getOriginalName(),
        ];

        foreach ($filePaths as $filePath) {
            if (file_exists($filePath)) {
                unlink($filePath);
            }
        }

    }

    protected function getUploadPath(FileMediaInterface $media): string
    {
        /** @var FileMediaTranslationInterface $trans */
        $trans = $media->getCurrentTranslation();
        $currentSite = $media->getSite();
        if (empty($currentSite)) {
            $currentSite = $this->siteContext->getSite();
        }
        $currentSiteDir = $currentSite->getSlug();

        $path = $this->projectDir
            // this segment could be changed for protected media, for example storing in /var/media for private files
            .'/public/media'
            .'/'.$currentSiteDir
            .'/'.$this->typeResolver->getTypeSlug(get_class($media));

        // maybe add year in path ? /upload/image/2025/file.jpg
        // would be less straightforward to list all files

        return $path;
    }
}
