<?php

namespace App\Infrastructure\Security;

use App\Support\Uuid;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JwtManager
{
    public function __construct(private array $config)
    {
    }

    public function issue(int $userId, int $roleId): array
    {
        $now = time();
        $jti = Uuid::v4();
        $payload = [
            'iss' => $this->config['issuer'] ?? 'emmanylcode-auth',
            'iat' => $now,
            'nbf' => $now,
            'exp' => $now + (int)($this->config['expiration'] ?? 3600),
            'sub' => (string)$userId,
            'user_id' => $userId,
            'role_id' => $roleId,
            'jti' => $jti,
        ];

        return [
            'token' => $this->encode($payload),
            'payload' => $payload,
        ];
    }

    public function decode(string $token): object
    {
        if (!empty($this->config['public_key'])) {
            return JWT::decode($token, new Key($this->config['public_key'], $this->config['alg'] ?? 'RS256'));
        }

        return JWT::decode($token, new Key($this->config['secret'] ?? 'auth-service-secret-key', 'HS256'));
    }

    public function publicKey(): ?string
    {
        return $this->config['public_key'] ?? null;
    }

    public function publicJwks(): array
    {
        $publicKey = $this->publicKey();
        if (!$publicKey) {
            return ['keys' => []];
        }

        $details = openssl_pkey_get_details(openssl_pkey_get_public($publicKey));
        $rsa = $details['rsa'] ?? null;
        if (!$rsa) {
            return ['keys' => []];
        }

        return [
            'keys' => [[
                'kty' => 'RSA',
                'use' => 'sig',
                'kid' => 'auth-service-current',
                'alg' => 'RS256',
                'n' => $this->base64Url($rsa['n']),
                'e' => $this->base64Url($rsa['e']),
            ]],
        ];
    }

    private function encode(array $payload): string
    {
        if (!empty($this->config['private_key'])) {
            return JWT::encode($payload, $this->config['private_key'], $this->config['alg'] ?? 'RS256', 'auth-service-current');
        }

        return JWT::encode($payload, $this->config['secret'] ?? 'auth-service-secret-key', 'HS256');
    }

    private function base64Url(string $value): string
    {
        return rtrim(strtr(base64_encode($value), '+/', '-_'), '=');
    }
}
