<?php

declare(strict_types=1);

namespace App\Providers;

use App\Models\AuditLog;
use App\Models\ConsentRecord;
use App\Models\Tenant;
use App\Models\User;
use App\Models\UserIdentity;
use App\Observers\AuditingObserver;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        //
    }

    public function boot(): void
    {
        // Global audit observer for the domain models we want to track.
        $audited = [Tenant::class, User::class, UserIdentity::class, ConsentRecord::class];

        foreach ($audited as $model) {
            $model::observe(AuditingObserver::class);
        }

        // Never audit AuditLog itself.
        AuditLog::unsetEventDispatcher();

        $this->configureRateLimiters();
    }

    /**
     * W·Dot v1.0 API rate limiting — config/wdot.php throttle 섹션 참조.
     *
     * Rate limit 이름:
     *   - api          → 일반 API (60/min/user|ip)
     *   - auth.login   → 로그인 (5/min/IP+email)
     *   - auth.register→ 회원가입 (3/min/IP)
     *   - api.heavy    → 검색/AI Studio (30/min/user)
     *   - api.payment  → 결제 (20/min/user)
     */
    private function configureRateLimiters(): void
    {
        $throttle = config('wdot.throttle', []);

        RateLimiter::for('api', static function (Request $r) use ($throttle) {
            $key = optional($r->user())->getAuthIdentifier() ?: $r->ip();

            return [Limit::perMinute((int) ($throttle['api'] ?? 60))->by((string) $key)];
        });

        RateLimiter::for('auth.login', static function (Request $r) use ($throttle) {
            $email = (string) $r->input('email', '');
            $key = $r->ip().'|'.mb_strtolower($email);

            return [Limit::perMinute((int) ($throttle['auth_login'] ?? 5))->by($key)];
        });

        RateLimiter::for('auth.register', static function (Request $r) use ($throttle) {
            return [Limit::perMinute((int) ($throttle['auth_register'] ?? 3))->by($r->ip())];
        });

        RateLimiter::for('api.heavy', static function (Request $r) use ($throttle) {
            $key = optional($r->user())->getAuthIdentifier() ?: $r->ip();

            return [Limit::perMinute((int) ($throttle['api_heavy'] ?? 30))->by((string) $key)];
        });

        RateLimiter::for('api.payment', static function (Request $r) use ($throttle) {
            $key = optional($r->user())->getAuthIdentifier() ?: $r->ip();

            return [Limit::perMinute((int) ($throttle['api_payment'] ?? 20))->by((string) $key)];
        });
    }
}
