<?php

namespace App\Doctrine\EventListener;

use Doctrine\ORM\Events;
use Psr\Log\LoggerInterface;
use App\Utils\ImageFixturesHelper;
use Doctrine\Common\EventSubscriber;
use Symfony\Component\Mime\MimeTypes;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Event\PrePersistEventArgs;
use App\Entity\Interface\IVideoCachableImage;
use Symfony\Component\Filesystem\Filesystem;
use Liip\ImagineBundle\Service\FilterService;
use Symfony\Component\HttpKernel\KernelInterface;
use Vich\UploaderBundle\Storage\StorageInterface;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Liip\ImagineBundle\Binary\Loader\FileSystemLoader;
use Liip\ImagineBundle\Binary\Locator\FileSystemLocator;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Symfony\Component\HttpFoundation\File\UploadedFile;

#[AsDoctrineListener(event: Events::preUpdate, priority: 500, connection: 'default')]
#[AsDoctrineListener(event: Events::prePersist, priority: 500, connection: 'default')]
class VideoImageCacheListener implements EventSubscriber
{
    public function __construct(
        private UploaderHelper $uploaderHelper,
        private CacheManager $cacheManager,
        private FilterService $filterService,
        private LoggerInterface $logger
    )
    {

    }

    public function preUpdate(PreUpdateEventArgs $args)
    {
        if (!$args->getObject() instanceof IVideoCachableImage) {
            return;
        }

        $this->_download_video_images($args->getObject());
    }

    public function prePersist(PrePersistEventArgs $args)
    {
        if (!$args->getObject() instanceof IVideoCachableImage) {
            return;
        }

        $this->_download_video_images($args->getObject());
    }

    private function _download_video_images(IVideoCachableImage $o_cachable): void
    {
        $imgHelper = new ImageFixturesHelper($this->logger);
        $propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
            ->enableExceptionOnInvalidIndex()
            ->getPropertyAccessor();
        $filesystem = new Filesystem();

        foreach ($o_cachable->getCachedVideoImages() as $video) {

            $video_url = $propertyAccessor->getValue($o_cachable, $video->field_name);
            if (!$video_url or $video_url == "") continue;

            $image_file = $propertyAccessor->getValue($o_cachable, $video->field_imageFileName);
            if ($image_file and $image_file != "") continue;

            $regex_youtube = "/^https:\/\/www.youtube.com\/watch\?v=([a-z_0-9]+)/i";
            $download_urls = [];
            $file_name = "";
            $mime_type = "";
            if (preg_match($regex_youtube, $video_url, $matches, PREG_OFFSET_CAPTURE)) {

                $youtube_key = $matches[1][0];
                $download_urls = [
                    "https://img.youtube.com/vi/$youtube_key/maxresdefault.jpg",
                    "https://img.youtube.com/vi/$youtube_key/sddefault.jpg",
                    "https://img.youtube.com/vi/$youtube_key/hqdefault.jpg",
                ];
                $file_name = "$youtube_key.jpg";
                $mime_type = "image/jpg";

            } else {
                continue;
            }

            $tmp_src = $filesystem->tempnam(sys_get_temp_dir(), 'youtube', '.jpg');

            foreach ($download_urls as $download_url) {
                $this->logger->info("[TRY] Download file $download_url");

                try {
                    file_put_contents($tmp_src, file_get_contents($download_url));
                    // echo "File downloaded successfully";
                    $this->logger->info("File downloaded successfully $download_url -> $tmp_src");
                    $file = new UploadedFile($tmp_src, $file_name, $mime_type, null, true);

                    $propertyAccessor->setValue($o_cachable, $video->field_imageFile, $file);
                    continue;
                } catch (\Throwable $th) {
                    $this->logger->critical("File downloaded FAILED $download_url");
                    $this->logger->critical($th->getMessage());
                }
            }

        }
    }

    public function getSubscribedEvents(): array
    {
        return [
            Events::preUpdate  => 'preUpdate',
            Events::prePersist => 'prePersist',
        ];
    }
}
