<?php

namespace App\Services;

use App\Repositories\AuthRepository;
use App\Repositories\LicenseRepository;
use Exception;

class AuthService
{

    private AuthRepository $authRepository;
    private LicenseRepository $licenseRepository;

    public function __construct()
    {
        $this->authRepository = new AuthRepository();
        $this->licenseRepository = new LicenseRepository();
    }

    /**
     * Login user
     * 
     * @throws Exception
     * 
     * @return array
     * 
     * @param string $username
     * @param string $password
     * @param string $license
     */
    public function login(string $username, string $password, string $license): array
    {
        $user = $this->authRepository->findUserWithLicense($username, $license);

        // Validates user and password
        if (!$user) {
            throw new Exception('INVALID_CREDENTIALS');
        }

        if (
            !empty($user['locked_until'])
        ) {
            $lockedUntil = new \DateTimeImmutable($user['locked_until']);
            $now = new \DateTimeImmutable('now');

            if ($lockedUntil > $now) {
                throw new Exception('ACCOUNT_LOCKED');
            }
        }

        if (!password_verify($password, $user['password_hash'])) {
            $this->authRepository->incrementFailedAttempts($user['client_id']);
            throw new Exception('INVALID_CREDENTIALS');
        }

        if (
            $user['expires_at'] !== null &&
            strtotime($user['expires_at']) < time()
        ) {
            $this->authRepository->incrementFailedAttempts($user['client_id']);
            throw new Exception('LICENSE_EXPIRED');
        }

        if ((int)$user['client_active'] !== 1) {
            $this->authRepository->incrementFailedAttempts($user['client_id']);
            throw new Exception('CLIENT_INACTIVE');
        }

        if ((int)$user['license_active'] !== 1) {
            $this->authRepository->incrementFailedAttempts($user['client_id']);
            throw new Exception('LICENSE_INACTIVE');
        }

        $this->authRepository->resetFailedAttempts($user['client_id']);
        $this->licenseRepository->revokeLicenseTokens($user['license_id']);

        $token = JwtService::generateToken([
            'uid' => $user['client_id'],
            'license_id' => $user['license_id'],
            'company_id' => $user['company_id']
        ]);

        return [
            'token' => $token,
            'expires_in' => (int) $_ENV['JWT_TTL']
        ];
    }
}
