<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\ApiPlatform;

use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use Contao\CoreBundle\Filesystem\VirtualFilesystemInterface;
use Contao\CoreBundle\Image\ImageFactoryInterface;
use Contao\Image\ResizeConfiguration;
use Ferienpass\CoreBundle\Entity\Offer\Base;
use Ferienpass\CoreBundle\Entity\Offer\OfferInterface;
use Ferienpass\CoreBundle\Entity\OfferMedia;
use Ferienpass\CoreBundle\Routing\OfferReaderUrl;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class OfferRepresentationProvider implements ProviderInterface
{
    public function __construct(
        #[Autowire(service: 'api_platform.doctrine.orm.state.item_provider')]
        private readonly ProviderInterface $itemProvider,
        #[Autowire(service: 'api_platform.doctrine.orm.state.collection_provider')]
        private readonly ProviderInterface $collectionProvider,
        private readonly UrlGeneratorInterface $urlGenerator,
        #[Autowire(service: 'contao.filesystem.virtual.media')]
        private readonly VirtualFilesystemInterface $filesystem,
        private readonly ImageFactoryInterface $imageFactory,
        #[Autowire(param: 'kernel.project_dir')]
        private readonly string $rootDir
    ) {
    }

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        if ($operation instanceof CollectionOperationInterface) {
            /** @var iterable<OfferInterface> $paginator */
            $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);

            foreach ($paginator as $item) {
                $this->setUrl($item);
                $this->setMedia($item, $context['request']);
            }

            return $paginator;
        }

        /** @var Base $item */
        $item = $this->itemProvider->provide($operation, $uriVariables, $context);
        if (!$item instanceof OfferInterface) {
            return $item;
        }

        $this->setUrl($item);
        $this->setMedia($item, $context['request']);

        return $item;
    }

    private function setUrl(OfferInterface $offer): void
    {
        try {
            $url = $this->urlGenerator->generate('cms', ['to' => 'offer_list', 'edition' => $offer->getEdition(), 'auto_item' => OfferReaderUrl::autoItem($offer)], UrlGeneratorInterface::ABSOLUTE_URL);

            $offer->setUrl($url);
        } catch (\RuntimeException) {
        }
    }

    private function setMedia(OfferInterface $offer, Request $request): void
    {
        /** @var Base $offer */
        $offer->setMediaForApi(array_filter(
            $offer->getMedia()->map(function (OfferMedia $media) use ($request): ?string {
                try {
                    $image = $this->imageFactory->create(
                        Path::join($this->rootDir, 'storage', 'media', $this->filesystem->get($media->getMedia()->getUuid())->getPath()),
                        new ResizeConfiguration()
                            ->setWidth(3000)
                            ->setHeight(3000)
                            ->setMode(ResizeConfiguration::MODE_BOX),
                    );
                } catch (\Throwable) {
                    return null;
                }

                return $image->getUrl($this->rootDir, $request->getSchemeAndHttpHost().'/');
            })->toArray()
        ));
    }
}
