<?php

namespace App\Providers;

use App\Events\CreditStatusSynced;
use App\Events\PaymentRegistered;
use App\Events\PaymentReversed;
use App\Listeners\CollectorSyncListener;
use App\Listeners\RefreshCreditStatusListener;
use App\Models\Credit;
use App\Observers\CreditObserver;
use App\Services\CreditStatusSyncService;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        $this->app->scoped(CreditStatusSyncService::class);
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Credit::observe(CreditObserver::class);
        $this->registerPaymentEventListeners();
        $this->registerRateLimiters();
    }

    /**
     * Registra los rate limiters de la aplicación.
     *
     * pwa-login: 5 intentos por minuto, clave = IP + identifier.
     * Usar IP+identifier (no solo IP) evita bloquear a toda una oficina
     * cuando múltiples usuarios comparten la misma IP pública.
     */
    protected function registerRateLimiters(): void
    {
        // Login: 5 intentos/min por IP+identifier (evita bloquear oficinas completas)
        RateLimiter::for('pwa-login', function (Request $request) {
            $key = sha1($request->ip().'|'.strtolower($request->input('identifier', '')));

            return Limit::perMinute(5)
                ->by($key)
                ->response(fn () => response()->json([
                    'message' => 'Demasiados intentos fallidos. Por favor espera un minuto e intenta de nuevo.',
                    'retry_after' => 60,
                ], 429));
        });

        // Escritura PWA: 60 operaciones/min por usuario autenticado.
        // Cubre: registro de pagos, sincronización batch, gastos, créditos, clientes.
        // Suficiente para operación normal de campo (cobrador activo hace ~10 pagos/hora).
        RateLimiter::for('pwa-write', function (Request $request) {
            $key = 'pwa-write|'.($request->user()?->id ?? $request->ip());

            return Limit::perMinute(60)
                ->by($key)
                ->response(fn () => response()->json([
                    'message' => 'Demasiadas operaciones en poco tiempo. Espera un momento e intenta de nuevo.',
                    'retry_after' => 60,
                ], 429));
        });
    }

    /**
     * Registra los listeners para eventos de pago y estado de crédito.
     */
    protected function registerPaymentEventListeners(): void
    {
        // Pagos → despacha Job asíncrono (SyncCreditStatusJob)
        Event::listen(
            PaymentRegistered::class,
            [RefreshCreditStatusListener::class, 'handlePaymentRegistered']
        );

        Event::listen(
            PaymentReversed::class,
            [RefreshCreditStatusListener::class, 'handlePaymentReversed']
        );

        // Evento interno: sincroniza orden de cobro cuando cambia el estado del crédito.
        // Escuchado desde el Job (síncrono dentro del worker), no desde el HTTP request.
        Event::listen(
            CreditStatusSynced::class,
            [CollectorSyncListener::class, 'handle']
        );
    }
}
