<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App\Models\IpData;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class IpLookupMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        if (get_setting('maintenance_status') === 'on' && Auth::check() && Auth::user()->role !== 'Superadmin') {
            Auth::logout();
            return redirect('/login')->withErrors(['error' => 'Website is under Maintenance, only Admins can login.']);
        }

        $service = get_setting('lookup_service');
        $proxycheck_api = get_setting('proxycheck_api');
        $ip = $request->ip();

        $availableServices = [
            'ip-api' => "http://ip-api.com/php/{$ip}?fields=status,country,countryCode,regionName,proxy",
            'proxycheck' => "https://proxycheck.io/v2/{$ip}?key={$proxycheck_api}&vpn=1&asn=1",
        ];

        if (!isset($availableServices[$service])) {
            return response()->json(['error' => 'Invalid IP lookup service'], 400);
        }

        $cacheKey = "ip_lookup_{$service}_{$ip}";
        $ipData = Cache::remember($cacheKey, now()->addHours(6), function () use ($ip, $service) {
            return IpData::where('ip', $ip)->where('api_service', $service)->first();
        });
        
        if ($ipData) {
            return $this->handleIpData($ipData, $next, $request);
        }

        try {
            $client = new Client(['timeout' => 5]);
            $response = $client->get($availableServices[$service]);

            $data = $this->parseResponse($service, $response->getBody()->getContents(), $ip);
            if (!$data) return $next($request);

            $ipData = IpData::create($data);

            return $this->handleIpData($ipData, $next, $request);
        } catch (\Exception $e) {
            Log::error('IP lookup failed: ' . $e->getMessage());
            return $next($request);
        }
    }

    private function parseResponse($service, $responseBody, $ip)
    {
        if ($service === 'proxycheck') {
            $data = json_decode($responseBody, true);
            if (!isset($data[$ip])) return null;

            return [
                'ip'           => $ip,
                'api_service'  => $service,
                'country'      => $data[$ip]['country'] ?? 'Unknown',
                'country_code' => $data[$ip]['isocode'] ?? null,
                'region_name'  => $data[$ip]['region'] ?? null,
                'is_proxy'     => $data[$ip]['proxy'] === 'yes' ? 1 : 0,
            ];
        }

        if ($service === 'ip-api') {
            $data = unserialize($responseBody);
            if ($data['status'] !== 'success') return null;

            return [
                'ip'           => $ip,
                'api_service'  => $service,
                'country'      => $data['country'] ?? 'Unknown',
                'country_code' => $data['countryCode'] ?? null,
                'region_name'  => $data['regionName'] ?? null,
                'is_proxy'     => $data['proxy'] ? 1 : 0,
            ];
        }

        return null;
    }

    private function handleIpData($ipData, $next, $request)
    {
        if ($ipData->is_proxy) {
            Auth::logout();
            return redirect('/login')->withErrors(['error' => 'Access denied: Proxy IP detected.']);
        }

        if (Auth::check()) {
            $user = Auth::user();

            if (empty($user->country) || strtolower($user->country) === 'unknown') {
                $user->update(['country' => $ipData->country_code]);
            }
            $allowed_mails = get_setting('allowed_mails');
            
            if (is_string($allowed_mails)) {
                $allowed_mails = trim($allowed_mails, '[]"');
                $allowed_mails = explode(',', $allowed_mails);
            } else {
                $allowed_mails = [];
            }
            $blocked_country = get_setting('blocked_countries');
            
            if (is_string($blocked_country)) {
                $blocked_country = json_decode($blocked_country, true);
            }
            
            $blocked_country = is_array($blocked_country) ? $blocked_country : [];
            
            if ($user->role !== 'Superadmin' && !empty($blocked_country) && in_array($user->country, $blocked_country)) {
                Auth::logout();
                return redirect('/login')->withErrors(['error' => 'Registration from this country is not allowed.']);
            }

            $email_domain = substr(strrchr($user->email, "@"), 1);
            
            if ($user->role !== 'Superadmin' && !empty($allowed_mails) && !in_array($email_domain, $allowed_mails)) {
                Auth::logout();
                return redirect('/login')->withErrors(['error' => 'The email domain is not allowed.']);
            }
            if ($user->role !== 'Superadmin' && $user->banned == 1) {
                Auth::logout();
                return redirect('/login')->withErrors(['error' => 'Access denied: Account Banned.']);
            }
        }

        return $next($request);
    }
}
