<?php

namespace App\Modules\Integrations\Platform\Services;

use App\Modules\Integrations\Platform\Models\ApiAuditLog;
use App\Modules\Integrations\Platform\Models\ApiSecurityEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

final class ApiSecurityMonitorService
{
    public function recordFromApiResponse(Request $request, int $status): void
    {
        if (! $request->is('api/v1/*')) {
            return;
        }
        if (! in_array($status, [401, 403, 429], true)) {
            return;
        }

        $type = match ($status) {
            401 => 'invalid_or_missing_token',
            403 => 'forbidden',
            429 => 'rate_limited',
            default => 'unknown',
        };

        ApiSecurityEvent::query()->create([
            'event_type' => $type,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'path' => '/'.$request->path(),
            'http_status' => $status,
            'meta' => ['request_id' => $request->attributes->get('request_id')],
            'created_at' => now(),
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public function summarize(int $hours = 24): array
    {
        $since = Carbon::now()->subHours(max(1, $hours));

        $counts = DB::table('api_security_events')
            ->where('created_at', '>=', $since)
            ->selectRaw('event_type, COUNT(*) as c')
            ->groupBy('event_type')
            ->pluck('c', 'event_type')
            ->all();

        $topIps = DB::table('api_security_events')
            ->where('created_at', '>=', $since)
            ->whereNotNull('ip_address')
            ->selectRaw('ip_address, COUNT(*) as c')
            ->groupBy('ip_address')
            ->orderByDesc('c')
            ->limit(10)
            ->get()
            ->map(fn ($r) => ['ip' => $r->ip_address, 'count' => (int) $r->c])
            ->all();

        $tokenAbuse = ApiAuditLog::query()
            ->where('created_at', '>=', $since)
            ->whereNotNull('api_token_id')
            ->where('status', '>=', 400)
            ->selectRaw('api_token_id, COUNT(*) as c')
            ->groupBy('api_token_id')
            ->orderByDesc('c')
            ->limit(10)
            ->get()
            ->map(fn ($r) => ['api_token_id' => (int) $r->api_token_id, 'errors' => (int) $r->c])
            ->all();

        $rate429 = (int) DB::table('api_audit_logs')
            ->where('created_at', '>=', $since)
            ->where('status', 429)
            ->count();

        return [
            'window_hours' => $hours,
            'security_events' => $counts,
            'top_ips' => $topIps,
            'token_error_spikes' => $tokenAbuse,
            'api_audit_429' => $rate429,
        ];
    }
}
