<?php

namespace AutoAdmin\Bundle\Media\Upload;

use AutoAdmin\Bundle\Admin\Configuration\ConfigManager;
use AutoAdmin\Bundle\Media\Library\LinkedMediaPropHelper;
use AutoAdmin\Bundle\Media\Library\MediaTypeResolver;
use AutoAdmin\Bundle\Media\Library\MediaPathGenerator;
use AutoAdmin\Bundle\Media\Model\Library\BaseMediaInterface;
use AutoAdmin\Bundle\Media\Model\Library\FileMediaInterface;
use AutoAdmin\Bundle\Media\Model\Library\FileMediaTranslationInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\PropertyAccess\PropertyAccessor;

class MediaRemoveHandler
{
    public function __construct(
        protected MediaPathGenerator $mediaUrlGenerator,
        protected ConfigManager $adminConfig,
        protected LinkedMediaPropHelper $linkedMediaPropHelper,
        protected MediaTypeResolver $mediaTypeResolver,
        protected EntityManagerInterface $em,
    ) {
    }

    protected function buildFilenames(BaseMediaInterface $media): array
    {
        $filenames = [];
        if ($media instanceof FileMediaInterface) {
            $filenames[] = $media->getOriginalName();
            /** @var FileMediaTranslationInterface $tr */
            $tr = $media->getCurrentTranslation();
            $filenames[] = $tr->getFileName();
        }

        return $filenames;
    }

    /*
     * One media could reference multiple files (original+renamed for example, maybe one file per translation?)
     */
    protected function generateFilePaths(BaseMediaInterface $media): array
    {
        $paths = [];

        foreach ($this->buildFilenames($media) as $filename) {
            $paths[] = $this->mediaUrlGenerator->generatePath($media, $filename);
        }

        return $paths;
    }

    public function handleRemove(FileMediaInterface $media)
    {
        $paths = $this->generateFilePaths($media);
        foreach ($paths as $path) {
            if (file_exists($path)) {
                unlink($path);
            }
        }

        $this->unlinkContents($media);
    }

    protected function unlinkContents(BaseMediaInterface $media)
    {
        $currentType = $this->mediaTypeResolver->getTypeSlug(get_class($media));
        $contentsConfig = $this->adminConfig->getConfig('entities');
        $entities = [];
        foreach ($contentsConfig as $contentConfig) {
            $propConfigs = $this->linkedMediaPropHelper->getLinkedProps($class = $contentConfig['class']);
            if ($propConfigs) {
                $entities[$class] = $propConfigs;
            }
        }

        $pa = new PropertyAccessor();
        foreach ($entities as $entityClass => $propConfigs) {
            foreach ($propConfigs as $propConfig) {
                $propName = $propConfig->getProp()->getName();
                $repo = $this->em->getRepository($entityClass);
                $qb = $repo->createQueryBuilder('_');
                $qb->andWhere('_.'.$propName.' = :linkedMediaString')
                    ->setParameter('linkedMediaString', $currentType.'#'.$media->getId());
                $results = $qb->getQuery()->getResult();
                if ($results) {
                    foreach ($results as $result) {
                        $pa->setValue($result, $propName, '');

                        $this->em->persist($result);
                    }
                    $this->em->flush();
                }
            }
        }
    }

    public function handleSoftRemove(FileMediaInterface $media)
    {
        throw new \RuntimeException('Media handleSoftRemove not implemented yet.');
    }
}
