<?php

namespace App\Http\Middleware;

use App\Models\Setting;
use Closure;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

class VerifyTorobJwt
{
    /** Official Torob Ed25519 public key (SPKI DER, base64) from Torob docs. */
    public const TOROB_PUBLIC_KEY_DER = 'MCowBQYDK2VwAyEAt6Mu4T0pBORY11W+QeM35UsmLO3vsf+6yKpFDEImFk0=';

    public function handle(Request $request, Closure $next): Response
    {
        if (!in_array((string) Setting::get('torob_api_enabled', '0'), ['1', 'true'], true)) {
            return response()->json(['error' => 'Torob API is disabled'], 503);
        }

        $token = $request->header('X-Torob-Token');
        if (!$token || !is_string($token)) {
            return response()->json(['error' => 'X-Torob-Token header is missing'], 401);
        }

        try {
            $seed = $this->publicKeySeed();
            // exp/nbf checked by library; aud must be checked manually (Torob PHP sample).
            $decoded = JWT::decode($token, new Key($seed, 'EdDSA'));
        } catch (Throwable $e) {
            return response()->json(['error' => 'Invalid Torob token: ' . $e->getMessage()], 401);
        }

        $expectedAud = $this->expectedAudience($request);
        $aud = $decoded->aud ?? null;
        if (!is_string($aud) || $aud !== $expectedAud) {
            return response()->json([
                'error' => 'Invalid audience. Expected "' . $expectedAud . '"',
            ], 401);
        }

        return $next($request);
    }

    /**
     * Torob PHP sample: last 32 bytes of DER as base64 seed for EdDSA.
     */
    public function publicKeySeed(): string
    {
        $der = base64_decode(self::TOROB_PUBLIC_KEY_DER, true);
        if ($der === false || strlen($der) < 32) {
            throw new \RuntimeException('Invalid Torob public key');
        }

        return base64_encode(substr($der, -32));
    }

    /**
     * aud = Host header value (domain[:port]), per Torob docs.
     */
    public function expectedAudience(Request $request): string
    {
        $configured = trim((string) Setting::get('torob_api_audience', ''));
        if ($configured !== '') {
            return $configured;
        }

        return $request->getHttpHost();
    }
}
