<?php

namespace App\Modules\Integrations\Platform\Middleware;

use App\Modules\Integrations\Platform\Models\ApiAuditLog;
use App\Modules\Integrations\Platform\Models\ApiToken;
use App\Modules\Integrations\Platform\Services\ApiSecurityMonitorService;
use Closure;
use Illuminate\Http\Request;

final class AuditApiRequest
{
    public function handle(Request $request, Closure $next)
    {
        $t0 = hrtime(true);

        $response = $next($request);

        if ($request->is('api/v1/*')) {
            $code = (int) $response->getStatusCode();
            $hasTenant = $request->attributes->get('tenant_id') !== null;
            if (in_array($code, [401, 403], true) || ($code === 429 && ! $hasTenant)) {
                app(ApiSecurityMonitorService::class)->recordFromApiResponse($request, $code);
            }
        }

        $tenantId = $request->attributes->get('tenant_id');
        if (is_int($tenantId) || (is_string($tenantId) && ctype_digit($tenantId))) {
            /** @var ApiToken|null $token */
            $token = $request->attributes->get('api_token');

            $routeName = $request->route()?->getName();
            $rid = $request->attributes->get('request_id');
            $durationMs = (int) round((hrtime(true) - $t0) / 1_000_000);

            ApiAuditLog::query()->create([
                'tenant_id' => (int) $tenantId,
                'api_token_id' => $token instanceof ApiToken ? (int) $token->id : null,
                'actor_type' => $token instanceof ApiToken ? 'api_token' : 'unknown',
                'actor_id' => $token instanceof ApiToken ? (int) $token->id : null,
                'method' => strtoupper((string) $request->getMethod()),
                'path' => '/'.$request->path(),
                'route_name' => is_string($routeName) ? $routeName : null,
                'status' => (int) $response->getStatusCode(),
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'request_id' => is_string($rid) ? $rid : null,
                'duration_ms' => $durationMs,
            ]);
        }

        return $response;
    }
}

