<?php

namespace AutoAdmin\Bundle\Media\Service;

use AutoAdmin\Bundle\Admin\Factory\ContentFactory;
use AutoAdmin\Bundle\Core\Helper\DoctrineHelper;
use AutoAdmin\Bundle\Media\Mapper\MapperManager;
use AutoAdmin\Bundle\Media\Model\FileInterface;
use AutoAdmin\Bundle\Media\Model\MediaInterface;
use AutoAdmin\Bundle\Media\Namer\NamerInterface;
use Symfony\Component\Filesystem\Filesystem;

class MediaManipulator
{
    protected ContentFactory $contentFactory;
    protected NamerInterface $namer;
    protected MapperManager $mapperManager;
    protected Filesystem $fileSystem;

    public function __construct(
        ContentFactory $contentFactory,
        NamerInterface $namer,
        MapperManager $mapperManager,
        FileSystem $fileSystem
    ) {
        $this->contentFactory = $contentFactory;
        $this->namer = $namer;
        $this->mapperManager = $mapperManager;
        $this->fileSystem = $fileSystem;
    }

    public function fileExists(FileInterface $media): bool
    {
        $origFilename = $media->getFileName();
        if ($origFilename) {
            $mapper = $this->mapperManager->getMapper($media);
            $path = $mapper->getUploadPath($media).DIRECTORY_SEPARATOR;

            return $this->fileSystem->exists($path.$media->getFileName());
        }

        return false;
    }

    public function duplicate(MediaInterface $media, MediaInterface $clone = null): ?MediaInterface
    {
        /** @var MediaInterface $newMedia */
        $newMedia = $clone ?? $this->contentFactory->createEntity(DoctrineHelper::removeProxyPrefix(get_class($media)));

        $mapper = $this->mapperManager->getMapper($media);
        $path = $mapper->getUploadPath($media).DIRECTORY_SEPARATOR;

        if (
            $media instanceof FileInterface
            && $newMedia instanceof FileInterface
            && $origFilename = $media->getFileName()
        ) {
            $newFilename = $this->namer->generateName($origFilename);
            $newMedia->setFileName($newFilename);
            $newMedia->setOriginalName($newFilename);

            // duplicate file
            if ($this->fileSystem->exists($path.$origFilename)) {
                $this->fileSystem->copy($path.$origFilename, $path.$newMedia->getFileName());
            }
        } else {
            $newMedia = null;
        }

        return $newMedia;
    }
}
