<?php

namespace apexl\Io\modules\user\services;

use apexl\hashing\Hash;
use apexl\Io\includes\HookManager;
use apexl\Io\modules\company\entities\companyEntity;
use apexl\Io\modules\user\entities\RefreshToken;
use apexl\Io\modules\user\entities\roleEntity;
use apexl\Io\modules\user\entities\sessionEntity;
use apexl\Io\modules\user\entities\userEntity;
use Exception;
use Psr\Http\Message\ServerRequestInterface as Request;
use TitleCase;
use function apexl\Io\config;

class userTools
{
    public function __construct(private HookManager $hookManager) {}

    /** @return string[] */
    public function splitNameToFirstAndLast($nameString): array
    {
        $nameParts = array_filter(explode(" ", (string) $nameString));
        $lastName = array_pop($nameParts);
        $firstName = implode(' ', $nameParts);
        $firstName = TitleCase::titleCase($firstName);
        $lastName = TitleCase::titleCase($lastName);

        return [$firstName, $lastName];
    }


    /**
     * @throws Exception
     * @deprecated
     */
    #[\Deprecated(message: 'Use apexl\\Io\\modules\\user\\Actions\\StartLoggedInSession')]
    public function startLoggedInSession(userEntity $user): array
    {
        $sessionId = bin2hex(random_bytes(20));
        $token = currentUser::createJWT(
            $user,
            $sessionId,
            config('auth.jwt.secret_key'),
            config('auth.jwt.algorithm'),
            config('auth.jwt.lifetime'),
        );

        //now we need to update the sessions table
        $session = new sessionEntity();
        $session->uid = $user->id;
        $session->sessionId = $sessionId;
        $session->created = time();
        $session->ended = 0;
        $session->active = 1;
        $session->store();

        $user->last_login = time();
        $user->store();

        // Generate and save refresh token
        $refreshToken = bin2hex(random_bytes(20));
        $refreshTokenEntity = new RefreshToken();
        $refreshTokenEntity->load($user->id);
        $refreshTokenEntity->user_id = $user->id;
        $refreshTokenEntity->token = hash('sha256', $refreshToken);
        $refreshTokenEntity->expiry = RefreshToken::newExpiryFrom();
        $refreshTokenEntity->store();

        return [$token, $refreshToken];
    }

    /**
     * @throws Exception
     */
    public function createCompanyUserWithPassword(
        Request $request,
        string $email,
        string $firstName,
        string $lastName,
        string $password,
        ?string $companyName = null
    ): ?userEntity {
        $user = new userEntity();
        $user->removeRoles();
        $user->first_name = $firstName;
        $user->last_name = $lastName;
        $user->email = $email;

        $role = new roleEntity();
        $role->loadByName('Company User');
        $user->addRole($role->id);

        if (!empty($password)) {
            $hash = new Hash();
            $hashData = $hash->hashString($password);
            $passwordHash = $hashData->hash;
            $passwordSalt = $hashData->salt;
            unset($password);
            $user->password = $passwordHash;
            $user->salt = $passwordSalt;
            $user->active = 1;
        }

        //Hook user pre save - allow other modules to act on the user save process, before storage.
        /** @var userEntity $user */
        $user = $this->hookManager->processHook('userPreSave', $user, $request);

        if ($user->isValid()) {
            $user->store();
            //Hook user post save - allow other modules to act on the user save process, after storage.
            /** @var userEntity $user */
            $user = $this->hookManager->processHook('userPostSave', $user, $request);

            if ($companyName && class_exists('apexl\Io\modules\company\entities\companyEntity')) {
                $company = new companyEntity();
                $company->CompanyName = $companyName;
                $company->CompanyContactEmail = $email;
                $company->Active = 1;
                $company->store();
                $company->storeCompanyUser($company->id, $user->id);
            }

            return $user;
        }

        return null;
    }
}
