<?php


namespace Opentalent\OtOptimizer\Middleware\Frontend;


use Opentalent\OtCore\Website\OtWebsiteRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\Controller\ErrorController;
use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;

class OtPageResolver extends \TYPO3\CMS\Frontend\Middleware\PageResolver
{
    private OtWebsiteRepository $otWebsiteRepository;

    /**
     * @param OtWebsiteRepository $otWebsiteRepository
     * @return void
     */
    public function injectOtWebsiteRepository(OtWebsiteRepository $otWebsiteRepository): void
    {
        $this->otWebsiteRepository = $otWebsiteRepository;
    }

    /**
     * Resolve the page ID
     *
     * @param ServerRequestInterface $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     * @throws \Opentalent\OtCore\Exception\NoSuchWebsiteException
     * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
     * @throws \TYPO3\CMS\Extbase\Object\Exception
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // Shall fall back on non-optimized mode if a cookie 'optimize' exists and is different from 1, or if
        // a server global variable TYPO3_OPTIMIZE is set and is different from 1
        $shallFallback = (isset($_COOKIE['optimize']) && (int)$_COOKIE['optimize'] !== 1 && (int)$_SERVER['TYPO3_OPTIMIZE'] !== 1);
        if ($shallFallback) {
            return parent::process($request, $handler);
        }

        $devMode = ($_SERVER['TYPO3_CONTEXT'] ?? '') == "Development";

        if (!$GLOBALS['TYPO3_REQUEST']) {
            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
                $request,
                'The requested website does not exist',
                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
            );
        }

        $website = $GLOBALS['TYPO3_REQUEST']->getAttribute('ot_website');
        $params = $request->getQueryParams();

        if (!($website['uid'] ?? 0) > 0) {
            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
                $request,
                'The requested website does not exist',
                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
            );
        }

        // if the page is requested from the BE module Viewpage or FrontendEditing, it shall be displayed even if hidden
        // a backend user shall be authenticated for this
        $requestedFromBE = (
                preg_match("/.+\/typo3\/index.php\?route=.*(Viewpage)|(FrontendEditing).*/", ($_SERVER['HTTP_REFERER'] ?? '')) ||
                ($request->getQueryParams()['frontend_editing'] ?? null) === 'true'
            )
            && $GLOBALS['BE_USER'];

        $pageUid = $this->otWebsiteRepository->matchUriToPage($website, $request->getUri(), $devMode, !$requestedFromBE);

        if (!$pageUid > 0) {
            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
                $request,
                'The requested page does not exist',
                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
            );
        }

        $params['id'] = $pageUid;
        $request = $request->withQueryParams($params);

        return parent::process($request, $handler);
    }
}
