<?php

declare(strict_types=1);

namespace KupShop\StorybookBundle\Controller;

use KupShop\ComponentsBundle\Utils\ComponentsLocator;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Util\System\UrlFinder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Environment;

class StorybookController extends AbstractController
{
    public function __construct(
        private readonly Environment $twig,
    ) {
    }

    private function parseRequestQuery(Request $request): array
    {
        return array_map(function ($item) {
            if ($result = json_decode($item, false)) {
                return $result;
            }

            return $item;
        }, $request->query->all());
    }

    #[Route(
        '/storybook/component/{id}',
        // The id can contain slashes, so we need to use a regex
        requirements: ['id' => '.+'],
    )]
    public function serveStorybookComponent(Request $request, string $id, ComponentsLocator $componentsLocator, UrlFinder $urlFinder): Response
    {
        $request->attributes->set('_storybook', true);

        // $id is the path to the Twig template in the storybook/ directory
        // Args are read from the query parameters and sent to the template
        $component = $componentsLocator->findComponentByName($id);

        // Force to generate absolute urls
        $urlFinder->setCdnPrefix(rtrim(Config::get()['Addr']['full'], '/'));

        $template = preg_replace('/\.\d+\.html\.twig/', '.stories.html.twig', $component['template']);
        $template_fallback = '@Components/storybook/preview.html.twig';

        $context = ['args' => $this->parseRequestQuery($request), 'id' => $id];
        $content = $this->twig->render($this->twig->resolveTemplate([$template, $template_fallback]), $context);

        // During development, storybook is served from a different port than the Symfony app
        // You can use nelmio/cors-bundle to set the Access-Control-Allow-Origin header correctly
        $headers = ['Access-Control-Allow-Origin' => '*'];

        return new Response($content, Response::HTTP_OK, $headers);
    }
}
