<?php

namespace apexl\Io\modules\userDisplay\controllers;

use apexl\Io\factories\RequestHelperFactory;
use apexl\Io\includes\Controller;
use apexl\Io\includes\HookManager;
use apexl\Io\includes\RouteManager;
use apexl\Io\modules\component\Factories\GenericComponentFactory;
use apexl\Io\modules\display\components\BasicLink;
use apexl\Io\modules\display\components\ContentTitle;
use apexl\Io\modules\display\services\Render;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\exceptions\UserAlreadyLoggedInException;
use apexl\Io\modules\user\services\CurrentUserFactory;
use apexl\Io\modules\userDisplay\FormBuilders\LoginFormBuilder;
use apexl\Io\modules\userDisplay\RequestHelper\LoginDisplayRequestHelper;
use apexl\Io\services\VariableManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

;

final readonly class LoginDisplayController extends Controller
{
    public function __invoke(
        Render $render,
        RouteManager $routeManager,
        CurrentUserFactory $currentUserFactory,
        GenericComponentFactory $componentFactory,
        VariableManager $variableManager,
        HookManager $hookManager,
        ServerRequestInterface $request,
        ResponseInterface $response,
        LoginFormBuilder $loginFormBuilder,
        RequestHelperFactory $requestHelperFactory,
        ?string $loginMessageType = null
    ): ResponseInterface {
        $requestHelper = $requestHelperFactory->make(LoginDisplayRequestHelper::class, $request);

        try {
            $this->assertNotLoggedIn($currentUserFactory->get());
        } catch (UserAlreadyLoggedInException) {
            $this->output->addRedirect('user.login.redirect', $requestHelper->redirect());

            return $this->json($response);
        }

        $render->setActive('noUI');
        $render->setPageTitle('Login');
        $components = $hookManager->processHook('login_page_components_before_form', []);

        if ($loginMessageType && $message = config(sprintf('auth.login_messages.%s', $loginMessageType))) {
            $components[] = $componentFactory->make(ContentTitle::class)
                ->addContent($message)
                ->addClass('text-light');
        }

        $components = [
            ...$components,
            $loginFormBuilder->build([
                'redirect' => $requestHelper->redirect(),
            ]),

            $componentFactory->make(BasicLink::class)
                ->addClass('forgottenPasswordLink')
                ->addRoute($routeManager->getRoutePattern('user.display.forgot-password'))
                ->addText($variableManager->get('user_login_forgot_password_text') ?? 'Forgot password?'),
        ];

        if (config('auth.users_can_register')) {
            $components[] = $componentFactory->make(BasicLink::class)
                ->addClass('registerLink')
                ->addRoute($routeManager->getRoutePattern('user.display.register'))
                ->addText($variableManager->get('user_login_register_text') ?? 'No account? Register.');
        }


        $components = $hookManager->processHook('login_page_components_after_form', $components);

        return $this->json($response, $render->build($components));
    }

    /**
     * @throws UserAlreadyLoggedInException
     */
    private function assertNotLoggedIn(userEntity $user): void
    {
        if ($user->isLoggedIn()) {
            throw new UserAlreadyLoggedInException($user->id);
        }
    }

}
