<?php

declare(strict_types=1);

namespace Apexl\Io\User\Actions;

use function Apexl\Config\config;
use Apexl\Config\Exceptions\MissingConfigException;
use Apexl\Io\User\Entities\UserEntity;
use Apexl\Io\User\Factories\RefreshTokenFactory;
use Apexl\Io\User\Interfaces\SessionManagerInterface;
use Apexl\Io\User\Services\JwtCreator;
use Exception;

use Random\RandomException;

final readonly class StartLoggedInSession
{
    public function __construct(
        private JwtCreator $jwtCreator,
        private RefreshTokenFactory $refreshTokenCreator,
        private SessionManagerInterface $sessionManager,
    ) {}

    /**
     * @throws MissingConfigException
     * @throws RandomException
     * @throws Exception
     */
    public function handle(UserEntity $user, bool $remember = false): array
    {
        $sessionId = $this->randomHexString();
        $token = $this->jwtCreator->forUser(
            $user,
            $sessionId,
        );

        $this->createSession($user->id, $sessionId);
        $this->updateUser($user);

        // "Stay signed in": store a longer per-row lifetime so this session
        // outlives a normal login. NULL keeps the config default.
        $lifetime = $remember ? (int) \Apexl\Config\config('auth.refresh.lifetime_remember') : null;
        $refreshToken = $this->refreshTokenCreator->create($user->id, $lifetime);

        return [$token, $refreshToken];
    }

    /**
     * @throws RandomException
     */
    private function randomHexString(): string
    {
        return bin2hex(random_bytes(20));
    }

    private function createSession(int $userId, string $sessionId): void
    {
        $this->sessionManager->create($userId, $sessionId);
    }

    /**
     * @throws Exception
     */
    private function updateUser(UserEntity $user): void
    {
        $user->last_login = time();
        $user->store();
    }
}