<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use App\Models\ApiKey;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Symfony\Component\HttpFoundation\Response;

/**
 * Аутентификация публичного API по ключу тенанта (G6).
 *
 * Ключ — `Authorization: Bearer lpkapi_...`. В БД лежит bcrypt key_hash + key_prefix
 * (первые 10 символов). Ищем кандидатов по префиксу через pgsql_supplier (BYPASSRLS —
 * публичный роут не ставит tenant-GUC, под RLS api_keys вернул бы пусто), затем
 * Hash::check. Успех → tenant_id в request->attributes (api_tenant_id) + last_used.
 */
class ApiKeyAuth
{
    public function handle(Request $request, Closure $next): Response
    {
        $key = $this->bearer($request);
        if ($key === null || $key === '') {
            return response()->json(['message' => 'Требуется API-ключ.'], 401);
        }

        $prefix = substr($key, 0, 10);

        $candidates = ApiKey::on('pgsql_supplier')
            ->where('key_prefix', $prefix)
            ->where('is_active', true)
            ->where('expires_at', '>', now())
            ->get();

        $matched = null;
        foreach ($candidates as $candidate) {
            if (Hash::check($key, (string) $candidate->key_hash)) {
                $matched = $candidate;
                break;
            }
        }

        if ($matched === null) {
            return response()->json(['message' => 'Неверный или неактивный API-ключ.'], 401);
        }

        if (! in_array('read', (array) $matched->scopes, true)) {
            return response()->json(['message' => 'Недостаточно прав ключа.'], 403);
        }

        ApiKey::on('pgsql_supplier')->whereKey($matched->getKey())->update([
            'last_used_at' => now(),
            'last_used_ip' => $request->ip(),
        ]);

        $request->attributes->set('api_tenant_id', (int) $matched->tenant_id);

        return $next($request);
    }

    private function bearer(Request $request): ?string
    {
        $header = (string) $request->header('Authorization', '');
        if (str_starts_with($header, 'Bearer ')) {
            return trim(substr($header, 7));
        }

        return null;
    }
}
