<?php

namespace Opentalent\OtTemplating\Page;

use Opentalent\OtCore\Website\OtPageRepository;
use Opentalent\OtCore\Website\OtWebsiteRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler;
use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3\CMS\Fluid\View\TemplateView;

class ErrorHandler implements PageErrorHandlerInterface
{
    const TEMPLATES_ROOT_PATHS = 'EXT:ot_templating/Resources/Private/Templates';
    const LAYOUTS_ROOT_PATHS = 'EXT:ot_templating/Resources/Private/Layouts';
    const PARTIALS_ROOT_PATHS = 'EXT:ot_templating/Resources/Private/Partials';

    const TEMPLATE_FILES = [
        403 => self::TEMPLATES_ROOT_PATHS . '/Page/Error/403.html',
        404 => self::TEMPLATES_ROOT_PATHS . '/Page/Error/404.html',
        500 => self::TEMPLATES_ROOT_PATHS . '/Page/Error/500.html'
    ];

    const REDIRECT_FALLBACK = 'https://opentalent.fr';

    /**
     * Status code of the response
     * @var int
     */
    protected int $statusCode;

    /**
     * Configuration of the error handler as set in site configuration.
     * @var array
     */
    protected array $errorHandlerConfiguration;

    /**
     * @var ViewInterface
     */
    protected $view;

    public function __construct(int $statusCode, array $configuration)
    {
        $this->statusCode = $statusCode;
        $this->errorHandlerConfiguration = $configuration;

        $this->view = GeneralUtility::makeInstance(TemplateView::class);

        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
        $controllerContext = $objectManager->get(ControllerContext::class);
        $renderingContext = $objectManager->get(RenderingContext::class);
        $webRequest = $objectManager->get(\TYPO3\CMS\Extbase\Mvc\Request::class);
        $webRequest->setControllerExtensionName('ot_templating');
        $controllerContext->setRequest($webRequest);
        $renderingContext->setControllerContext($controllerContext);

        $this->view->setRenderingContext($renderingContext);
        $this->view->setTemplateRootPaths([self::TEMPLATES_ROOT_PATHS]);
        $this->view->setLayoutRootPaths([self::LAYOUTS_ROOT_PATHS]);
        $this->view->setPartialRootPaths([self::PARTIALS_ROOT_PATHS]);
        $this->view->setTemplatePathAndFilename(
            GeneralUtility::getFileAbsFileName(self::TEMPLATE_FILES[$statusCode])
        );
    }

    /**
     * @param ServerRequestInterface $request
     * @param string $message
     * @param array $reasons
     * @return ResponseInterface
     */
    public function handlePageError(
        ServerRequestInterface $request,
        string $message,
        array $reasons = []
    ): ResponseInterface {

        $homeUri = "https://opentalent.fr";
        $title = 'Page Introuvable';

        // This variable aims to prevent redirection loop
        $isCircular = preg_match('/.*\/page-introuvable/', $request->getUri()->getPath());

        $otWebRepository = GeneralUtility::makeInstance(ObjectManager::class)->get(OtWebsiteRepository::class);
        $website = $otWebRepository->getCurrentWebsiteFromFEGlobals();

        if ($website && !$isCircular){

            $homeUri = $otWebRepository->resolveWebsiteBaseUri($website);
            $rootUid = $otWebRepository->getWebsiteRootUid($website['uid']);

            $pageRepository = GeneralUtility::makeInstance(ObjectManager::class)->get(OtPageRepository::class);
            $rootPage = $pageRepository->getPage($rootUid);
            if (!empty($rootPage)) {

                $title = $rootPage['title'];

                $subPages = $pageRepository->getAllSubpagesForPage($rootUid, true);
                foreach ($subPages as $page) {
                    if ($page['tx_fed_page_controller_action'] == 'OpenTalent.OtTemplating->error/404') {

                        $errorHandler = GeneralUtility::makeInstance(
                            PageContentErrorHandler::class,
                            $this->statusCode,
                            [
                                'errorHandler' => 'Page',
                                'errorContentSource' => 't3://page?uid=' . $page['uid']
                            ]
                        );
                        return $errorHandler->handlePageError($request, $message, $reasons);
                    }
                }
            } else {
                $title = 'Page Introuvable';
                $homeUri = self::REDIRECT_FALLBACK;
            }

        }

        // At this point, the site has not been determined or
        //   this site has no subpage with slug '/page-introuvable'
        $this->view->assignMultiple([
            'request' => $request,
            'message' => $message,
            'reasons' => $reasons,
            'homeUri' => $homeUri,
            'siteTitle' => $title
        ]);

        return new HtmlResponse($this->view->render(), $this->statusCode);
    }

}
