<?php

namespace App\Libraries;

use stdClass;

/**
 * JWT auth for API: generate and validate Bearer tokens (pure PHP, no deps).
 */
class JwtAuth
{
    private static ?object $currentUser = null;

    public static function generate(int $userId, string $phone, string $role): string
    {
        $payload = [
            'sub'   => (string) $userId,
            'phone' => $phone,
            'role'  => $role,
            'iat'   => time(),
            'exp'   => time() + (30 * 24 * 3600), // 30 days
        ];

        $header = ['typ' => 'JWT', 'alg' => 'HS256'];
        $b64h   = self::base64UrlEncode(json_encode($header));
        $b64p   = self::base64UrlEncode(json_encode($payload));
        $sig    = hash_hmac('sha256', $b64h . '.' . $b64p, self::getSecretKey(), true);

        return $b64h . '.' . $b64p . '.' . self::base64UrlEncode($sig);
    }

    public static function decode(?string $token): ?stdClass
    {
        if (empty($token)) {
            return null;
        }
        $token = preg_replace('/^Bearer\s+/i', '', trim($token));
        $parts = explode('.', $token);
        if (count($parts) !== 3) {
            return null;
        }
        try {
            $payloadJson = self::base64UrlDecode($parts[1]);
            if ($payloadJson === false) {
                return null;
            }
            $payload = json_decode($payloadJson);
            if (! $payload || ! isset($payload->exp, $payload->sub)) {
                return null;
            }
            if ($payload->exp < time()) {
                return null;
            }
            $sigExpected = hash_hmac('sha256', $parts[0] . '.' . $parts[1], self::getSecretKey(), true);
            $sigActual   = self::base64UrlDecode($parts[2]);
            if ($sigActual === false || ! hash_equals($sigExpected, $sigActual)) {
                return null;
            }

            return $payload;
        } catch (\Throwable) {
            return null;
        }
    }

    public static function setCurrentUser(object $user): void
    {
        self::$currentUser = $user;
    }

    public static function user(): ?object
    {
        return self::$currentUser;
    }

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

    private static function base64UrlDecode(string $data): string|false
    {
        return base64_decode(strtr($data, '-_', '+/'), true);
    }

    private static function getSecretKey(): string
    {
        $key = env('jwt.secret');
        if (empty($key)) {
            try {
                $key = config('Encryption')->key ?? '';
            } catch (\Throwable) {
                $key = '';
            }
        }
        if (empty($key)) {
            $key = 'jambo-default-secret-change-in-production';
        }
        if (strlen($key) < 32) {
            $key = hash('sha256', $key);
        }

        return $key;
    }
}
