<?php


namespace AutoAdmin\Bundle\Content\Controller;

use AutoAdmin\Bundle\Content\Model\PageInterface;
use AutoAdmin\Bundle\Content\Routing\ContentRouter;
use AutoAdmin\Bundle\Content\Site\SiteConfigBuilderHelper;
use AutoAdmin\Bundle\Content\Site\SiteContextHelper;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Service\Attribute\Required;

class I18nRedirectController extends AbstractContentController
{
    protected SiteConfigBuilderHelper $siteConfigBuilder;
    protected SiteContextHelper $siteContextHelper;
    protected ContentRouter $contentRouter;

    #[Required]
    public function inject(
        SiteConfigBuilderHelper $siteConfigBuilder,
        SiteContextHelper $siteContextHelper,
        ContentRouter $contentRouter,
    ): void {
        $this->siteConfigBuilder = $siteConfigBuilder;
        $this->siteContextHelper = $siteContextHelper;
        $this->contentRouter = $contentRouter;
    }

    /**
     * All parameters can be used from a routing.yaml config file, so keep them
     *
     * @param Request $request
     * @param string $path
     * @param bool $permanent
     * @param string|null $scheme
     * @param string|null $port
     * @return RedirectResponse
     */
    public function rootRedirect(
        Request $request,
        string $path = '',
        bool $permanent = true,
        string $scheme = null,
        string $port = null
    ): RedirectResponse {
        $isRootRedirect = $path == '';
        if ($isRootRedirect && $redirect = $this->handleAcceptLanguage($request)) {
            return $redirect;
        }

        if (strlen($path) <= 1) {
            throw new InvalidArgumentException('No path given for "i18nRedirect" route.');
        }

        $statusCode = $permanent ? Response::HTTP_MOVED_PERMANENTLY : Response::HTTP_FOUND;

        // redirect if the path is a full URL
        if (parse_url($path, PHP_URL_SCHEME)) {
            return new RedirectResponse($path, $statusCode);
        }

        if (null === $scheme) {
            $scheme = $request->getScheme();
        }

        $qs = $request->getQueryString();
        if ($qs) {
            $qs = str_contains($path, '?') ? '&'.$qs : '?'.$qs;
        }

        $port = $port === null ? '' : (':'.$port);

        $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs;


        return new RedirectResponse($url, $statusCode);
    }

    /**
     * @param Request $request
     * @param string $path
     * @param bool $permanent
     * @param string|null $scheme
     * @param string|null $port
     * @return RedirectResponse
     *
     * @deprecated use {@see rootRedirect}
     *
     */
    public function internationalizationRedirect(
        Request $request,
        string $path = '',
        bool $permanent = true,
        string $scheme = null,
        string $port = null
    ): RedirectResponse {
        return $this->rootRedirect(...func_get_args());
    }

    protected function handleAcceptLanguage(Request $request): ?RedirectResponse
    {
        $parsedLocales = [];
        if ($acceptLanguage = $request->headers->get('Accept-language')) {
            $parsedLocales = $this->getLocalesFromAcceptLanguage($acceptLanguage);
        }

        $siteConfigs = $this->siteContextHelper->getCurrentContextSiteConfigs();
        $matchedSite = $siteConfigs[0];// defaulting to first
        if ($parsedLocales) {
            foreach ($siteConfigs as $siteConfig) {
                if (in_array($siteConfig->getLocale()->getCode(), $parsedLocales)) {
                    $matchedSite = $siteConfig;
                    break;
                }
            }
        }

        $homepage = $this->em->getRepository(PageInterface::class)->contentFindOneBy(['_.homepage' => true,]);

        $options = ['locale' => $matchedSite->getLocale()->getCode()];
        if ($request->getHost() != $domHost = $matchedSite->getDomain()->getDomain()) {
            $options['host'] = $domHost;
        }
        $url = $this->contentRouter->generate(
            $homepage,
            null,
            ['_locale' => $matchedSite->getLocale()->getCode()],
            $options,
        );

        return new RedirectResponse($url, Response::HTTP_FOUND, ['x-custom-aa-root-redirect' => 1]);
    }


    /**
     * reference regarding format here https://www.rfc-editor.org/rfc/rfc7231#section-5.3.5
     * used to convert Accept-Language header value to a list of language_country xx_XX combinations (e.g. fr_FR)
     *
     * example values:
     * fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,de;q=0.6
     * en-US,en
     *
     * @param string $acceptedLanguageHeader
     * @return array
     */
    protected function getLocalesFromAcceptLanguage(string $acceptedLanguageHeader): array
    {
        $pattern = '/([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})*)(;q=(0(\.[0-9]{1,3})?|1(\.0{1,3})?))?/';

        preg_match_all($pattern, $acceptedLanguageHeader, $matches, PREG_SET_ORDER);

        $locales = array_column($matches, 1);

        // swap from rfc using - to _ for our usage
        $locales = array_map(fn($v) => str_replace('-', '_', $v), $locales);

        return array_unique(array_filter($locales));
    }
}
