<?php

namespace apexl\Io\modules\user\controllers;

use apexl\Io\includes\Controller;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\services\currentUser;
use apexl\Io\modules\user\services\userTools;
use apexl\Io\services\Output;
use apexl\Vault\exceptions\ExecutionException;
use Exception;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

final readonly class LoginByKeyController extends Controller
{
    public function __construct(
        Output $output,
    ) {
        parent::__construct($output);
    }


    /**
     * @throws ExecutionException
     * @throws Exception
     */
    public function __invoke(
        userTools $userTools,
        ServerRequestInterface $request,
        ResponseInterface $response
    ): ResponseInterface {
        //is this allowed?
        if (config('auth.enableQueryStringLogin')) {
            $uid = $request->getAttribute('user'); // set in an earlier middleware
            if ($uid != 0) {
                //already logged in? Return with a redirect to the home page.
                if ($redirect = ((object) $request->getParsedBody())->redirect ?? '/') {
                    $this->output->addRedirect('user.login.redirect', $redirect);
                }
                //return without doing anything.
                return $this->json($response);
            }

            $body = (object) $request->getParsedBody();
            if (!empty($body) && isset($body->nfc_key)) {

                //we're not logged in, so lets check if we have the appropriate query string, and a valid key.
                $user = new userEntity();
                $user->getUserByNfcKey($body->nfc_key);

                //make sure we have a valid record and we're an active user.
                if ($user->email !== null && $user->active == 1) {
                    //login
                    $this->loginPostAuth($userTools, $user, $request);
                    if ($redirect = $body->redirect ?? '/') {
                        $this->output->addRedirect('user.login.redirect', $redirect);
                    }
                    return $this->json($response);
                }
            }
            $this->output->addMessage(
                'user.login.validation',
                'error',
                'The provided key doesn\'t match, or the user is locked.'
            );
            $this->output->addResponse($request, [], false); // added so we can hook into this elsewhere.

            return $this->json($response, [], 400);
        }

        return $this->json($response, ['error' => 'Logging in by Key is not allowed on this system'], 403);
    }

    /**
     * Allows other processes to force a user login without requiring a password. (Login by URL, Switch User etc)
     * @throws Exception
     */
    protected function loginPostAuth(userTools $userTools, $user, $request): void
    {
        [$authToken, $refreshToken] = $userTools->startLoggedInSession($user);
        //allow others to act on this response. Hook is keyed by route name.
        $this->output->addResponse(
            $request,
            [
                'access_token' => $authToken,
                'refresh_token' => $refreshToken,
                'expires_in' => currentUser::getTokenExpiryFromNow($authToken),
            ]
        );
    }
}
