<?php

namespace App\Http\Middleware;

use App\Services\Notification\TelegramService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;

class IpAccessControl
{
    /**
     * Handle an incoming request.
     *
     * @param  Closure(Request): (Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $ip = $request->ip();

        // Batch get common settings to reduce function overhead
        $settings = [
            'blacklist' => get_setting('ip_blacklist', ''),
            'whitelist_admin' => get_setting('ip_whitelist_admin', ''),
            'auto_block' => get_setting('auto_block_ip', false),
            'single_session' => get_setting('session_single_session', false),
            'hsts' => get_setting('hsts_enabled', false),
        ];

        // 1. GLOBAL BLACKLIST
        $blacklistArr = array_filter(array_map('trim', explode(',', $settings['blacklist'])));
        if (in_array($ip, $blacklistArr)) {
            abort(403, 'Your IP address has been blocked.');
        }

        // 2. ADMIN WHITELIST (Protects specific routes)
        // Check if current route is an admin/restricted route
        if ($request->is('system-config*') || $request->is('users*') || $request->is('roles*') || $request->is('permissions*') || $request->is('backups*') || $request->is('admin/*')) {
            $whitelistArr = array_filter(array_map('trim', explode(',', $settings['whitelist_admin'])));
            if (! empty($whitelistArr) && ! in_array($ip, $whitelistArr)) {
                abort(403, 'Access denied: Admin IP Whitelist restricted.');
            }
        }

        // 3. RATE LIMITING & AUTO BLOCK
        if ($settings['auto_block']) {
            $cacheKey = "ip_block:{$ip}";
            if (Cache::has($cacheKey)) {
                abort(429, 'Your IP has been temporarily blocked due to excessive requests.');
            }

            $threshold = get_setting('threshold_auto_block', 100);

            $hitKey = "ip_hits:{$ip}";
            Cache::add($hitKey, 0, now()->addMinute());
            $hits = Cache::increment($hitKey);

            if ($hits > $threshold) {
                Cache::put($cacheKey, true, now()->addHours(24));

                // 🚨 Send Security Alert to Telegram
                try {
                    $telegram = app(TelegramService::class);
                    $msg = "<b>[FIREWALL BLOCK]</b>\n\n";
                    $msg .= "IP Address: <code>{$ip}</code>\n";
                    $msg .= "Reason: <b>Excessive Requests</b> ({$hits} hits)\n";
                    $msg .= "Action: <b>Auto-Blocked (24h)</b>\n\n";
                    $msg .= "Check configuration: <a href='".url('/system-config')."'>Admin Panel</a>";
                    $telegram->sendMessage($msg);
                } catch (\Exception $e) {
                    \Log::error('Firewall Telegram Alert Failed: '.$e->getMessage());
                }

                abort(429, 'Excessive requests detected. Your IP has been blocked for 24 hours.');
            }
        }

        // 4. SINGLE SESSION ENFORCEMENT
        // Skip check if we are currently impersonating to prevent logout
        if ($request->user() && $settings['single_session'] && ! session()->has('impersonator_id')) {
            if ($request->user()->last_session_id !== session()->getId()) {
                Auth::logout();

                return redirect()->route('login')->with('error', 'You have been logged out because another device logged into your account.');
            }
        }

        $response = $next($request);

        // 5. HSTS (Transport Security)
        if ($request->isSecure() && $settings['hsts']) {
            $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
        }

        return $response;
    }
}
