<?php

namespace App\Http\Middleware;

use Carbon\CarbonImmutable;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ValidateControlCenterAgentRequest
{
    public function handle(Request $request, Closure $next): Response
    {
        $token = (string) env('CONTROL_CENTER_AGENT_TOKEN');
        $secret = (string) env('CONTROL_CENTER_AGENT_SECRET', $token);
        $timestamp = (string) $request->header('X-Control-Timestamp');
        $signature = (string) $request->header('X-Control-Signature');
        $ttl = (int) env('CONTROL_CENTER_AGENT_TTL', 300);

        abort_unless(
            hash_equals($token, (string) $request->bearerToken()),
            401,
            'Invalid bearer token.'
        );

        $parsedTimestamp = rescue(
            fn () => CarbonImmutable::parse($timestamp),
            fn () => null,
            report: false,
        );

        abort_unless($parsedTimestamp instanceof CarbonImmutable, 401, 'Invalid timestamp.');
        abort_unless(abs(now()->diffInSeconds($parsedTimestamp, false)) <= $ttl, 401, 'Timestamp expired.');

        $path = '/'.ltrim($request->path(), '/');
        $basePath = '/api/control-center-agent';
        $signedPath = str_starts_with($path, $basePath) ? substr($path, strlen($basePath)) : $path;
        $signedPath = $signedPath === '' ? '/' : $signedPath;

        $expected = hash_hmac(
            'sha256',
            strtoupper($request->method())."|{$signedPath}|{$timestamp}",
            $secret ?: $token
        );

        abort_unless(hash_equals($expected, $signature), 401, 'Invalid request signature.');

        return $next($request);
    }
}
