<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Models\RateLimit;
use Illuminate\Support\Facades\Log;

class RateLimitMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next, string $type = 'ip'): Response
    {
        try {
            $key = $this->generateKey($request, $type);
            $config = $this->getConfigForType($type);
            
            if (!RateLimit::isAllowed($key, $config)) {
                $rateLimit = RateLimit::getByKey($key);
                
                Log::warning('Rate limit exceeded', [
                    'key' => $key,
                    'ip' => $request->ip(),
                    'user_id' => $request->user()?->id,
                    'endpoint' => $request->path(),
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Rate limit exceeded. Please try again later.',
                    'retry_after' => $rateLimit ? $rateLimit->getResetTime()->diffInSeconds() : 60,
                ], 429);
            }

            $response = $next($request);
            
            // Add rate limit headers to response
            if ($rateLimit = RateLimit::getByKey($key)) {
                $response->headers->set('X-RateLimit-Limit', $rateLimit->limit);
                $response->headers->set('X-RateLimit-Remaining', $rateLimit->getRemaining());
                $response->headers->set('X-RateLimit-Reset', $rateLimit->getResetTime()->timestamp);
                
                if ($rateLimit->isBlocked()) {
                    $response->headers->set('Retry-After', $rateLimit->blocked_until->diffInSeconds());
                }
            }

            return $response;

        } catch (\Exception $e) {
            Log::error('Rate limiting error: ' . $e->getMessage());
            // Fail open - allow request through if rate limiting fails
            return $next($request);
        }
    }

    /**
     * Generate rate limit key based on type
     */
    private function generateKey(Request $request, string $type): string
    {
        switch ($type) {
            case 'user':
                $userId = $request->user()?->id ?? 'guest';
                return "user:{$userId}:" . $request->path();
                
            case 'ip':
                return "ip:" . $request->ip() . ":" . $request->path();
                
            case 'api_key':
                $apiKey = $request->header('X-API-Key') ?? 'no-key';
                return "api:{$apiKey}:" . $request->path();
                
            case 'user_orders':
                $userId = $request->user()?->id ?? 'guest';
                return "user_orders:{$userId}";
                
            case 'user_withdrawals':
                $userId = $request->user()?->id ?? 'guest';
                return "user_withdrawals:{$userId}";
                
            default:
                return "default:" . $request->ip() . ":" . $request->path();
        }
    }

    /**
     * Get configuration for rate limit type
     */
    private function getConfigForType(string $type): array
    {
        switch ($type) {
            case 'user_orders':
                return RateLimit::CONFIG_USER_ORDERS;
                
            case 'user_withdrawals':
                return RateLimit::CONFIG_USER_WITHDRAWALS;
                
            case 'api_key':
                return RateLimit::CONFIG_API_KEY_ORDERS;
                
            case 'user':
                return [
                    'limit' => 500,
                    'window_seconds' => 3600,
                    'key_prefix' => 'user_requests'
                ];
                
            case 'ip':
            default:
                return RateLimit::CONFIG_IP_REQUESTS;
        }
    }
}