<?php

declare(strict_types=1);

namespace App\Providers;

use App\Models\Group;
use App\Models\Household;
use App\Models\Member;
use App\Models\MemberTransfer;
use App\Observers\AuditOnlyObserver;
use App\Observers\MemberObserver;
use App\Policies\TransferPolicy;
use App\Services\BranchAccessService;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(BranchAccessService::class);
    }

    public function boot(): void
    {
        Member::observe(MemberObserver::class);
        Household::observe(AuditOnlyObserver::class);
        Group::observe(AuditOnlyObserver::class);

        Gate::policy(MemberTransfer::class, TransferPolicy::class);

        Model::preventLazyLoading(! app()->isProduction());

        RateLimiter::for('login', function (Request $request) {
            $key = strtolower((string) $request->input('email')).'|'.$request->ip();

            return Limit::perMinute(5)->by($key);
        });

        // Sensible global ceiling for authenticated API traffic — generous
        // enough for normal UI polling (imports/exports poll every 2s) but
        // stops a runaway client or script from hammering the DB-backed
        // queue/cache on shared hosting.
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(180)->by($request->user()?->id ?: $request->ip());
        });

        // Search hits FULLTEXT/LIKE queries on every keystroke from a
        // debounced but still-frequent typeahead — keep it tighter.
        RateLimiter::for('search', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
}
