<?php

namespace App\Services\Fraud\Checks;

use App\Models\Order;
use App\Models\OrderFraudCheck;
use App\Models\Setting;
use Illuminate\Support\Facades\Http;

/**
 * IP Reputation Check
 *
 * IP adresinin itibarını kontrol eder
 * - VPN/Proxy kullanımı
 * - Tor exit node
 * - Bilinen kötü IP'ler
 * - Coğrafi konum
 */
class IpReputationCheck extends BaseFraudCheck
{
    protected int $priority = 20;

    public function getName(): string
    {
        return 'IP Reputation Check';
    }

    public function getType(): string
    {
        return OrderFraudCheck::TYPE_IP_REPUTATION;
    }

    public function getDescription(): string
    {
        return 'Checks IP address reputation, VPN/Proxy detection, and geo-location';
    }

    public function isEnabled(): bool
    {
        if (!empty($this->moduleConfig)) {
            return !empty($this->moduleConfig['ip_check_enabled']);
        }

        return (bool) Setting::getValue('fraud_ip_check_enabled', true);
    }

    public function check(Order $order): array
    {
        $ipAddress = $order->ip_address;

        if (!$ipAddress) {
            return $this->skipped('No IP address provided');
        }

        // Localhost veya private IP'leri skip et
        if ($this->isPrivateIp($ipAddress)) {
            return $this->skipped('Private or localhost IP address');
        }

        // IP reputation kontrolü
        $reputationData = $this->checkIpReputation($ipAddress);

        $data = [
            'ip_address' => $ipAddress,
            'is_vpn' => $reputationData['is_vpn'] ?? false,
            'is_proxy' => $reputationData['is_proxy'] ?? false,
            'is_tor' => $reputationData['is_tor'] ?? false,
            'is_datacenter' => $reputationData['is_datacenter'] ?? false,
            'country_code' => $reputationData['country_code'] ?? null,
            'city' => $reputationData['city'] ?? null,
            'risk_score' => $reputationData['risk_score'] ?? 0,
            'reputation_service' => $reputationData['service'] ?? 'internal',
        ];

        // TOR kullanımı - Critical (eğer ayardan aktifse)
        if (!empty($this->moduleConfig)) {
            $blockTor = !empty($this->moduleConfig['block_tor']);
        } else {
            $blockTor = (bool) Setting::getValue('fraud_block_tor', true);
        }
        if ($blockTor && ($reputationData['is_tor'] ?? false)) {
            return $this->failed(
                95,
                'Order placed from TOR exit node',
                $data
            );
        }

        // VPN/Proxy kullanımı - High risk (eğer ayardan aktifse)
        if (!empty($this->moduleConfig)) {
            $blockVpnProxy = !empty($this->moduleConfig['block_vpn_proxy']);
        } else {
            $blockVpnProxy = (bool) Setting::getValue('fraud_block_vpn_proxy', false);
        }
        if ($blockVpnProxy && ($reputationData['is_vpn'] ?? false)) {
            return $this->failed(
                75,
                'Order placed from VPN connection',
                $data
            );
        }

        if ($blockVpnProxy && ($reputationData['is_proxy'] ?? false)) {
            return $this->failed(
                70,
                'Order placed from proxy server',
                $data
            );
        }

        // VPN/Proxy engelleme kapalıysa warning ver
        if (!$blockVpnProxy) {
            if ($reputationData['is_vpn'] ?? false) {
                return $this->warning(
                    40,
                    'Order placed from VPN connection (warning only)',
                    $data
                );
            }

            if ($reputationData['is_proxy'] ?? false) {
                return $this->warning(
                    35,
                    'Order placed from proxy server (warning only)',
                    $data
                );
            }
        }

        // TOR ama engelleme kapalıysa warning ver
        if (!$blockTor && ($reputationData['is_tor'] ?? false)) {
            return $this->warning(
                60,
                'Order placed from TOR exit node (warning only)',
                $data
            );
        }

        // Datacenter IP - Medium risk
        if ($reputationData['is_datacenter'] ?? false) {
            return $this->warning(
                30,
                'Order placed from datacenter IP',
                $data
            );
        }

        // High risk country check
        if (!empty($this->moduleConfig['high_risk_countries'])) {
            $highRiskCountries = array_map('trim', explode(',', $this->moduleConfig['high_risk_countries']));
            $highRiskCountries = array_filter($highRiskCountries);
        } else {
            $highRiskCountries = [];
        }
        if (!empty($highRiskCountries) && in_array($reputationData['country_code'] ?? '', $highRiskCountries)) {
            return $this->warning(
                40,
                'Order from high-risk country: ' . $reputationData['country_code'],
                $data
            );
        }

        // External service risk score
        $externalRiskScore = $reputationData['risk_score'] ?? 0;
        if ($externalRiskScore >= 80) {
            return $this->failed(
                $externalRiskScore,
                'IP has high fraud risk score from reputation service',
                $data
            );
        } elseif ($externalRiskScore >= 50) {
            return $this->warning(
                $externalRiskScore,
                'IP has moderate fraud risk score from reputation service',
                $data
            );
        }

        return $this->passed('IP reputation is clean', $data);
    }

    /**
     * Check if IP is private/localhost
     */
    protected function isPrivateIp(string $ip): bool
    {
        // IPv4 private ranges
        $privateRanges = [
            '10.0.0.0/8',
            '172.16.0.0/12',
            '192.168.0.0/16',
            '127.0.0.0/8',
        ];

        foreach ($privateRanges as $range) {
            if ($this->ipInRange($ip, $range)) {
                return true;
            }
        }

        return $ip === '::1' || $ip === 'localhost';
    }

    /**
     * Check if IP is in CIDR range
     */
    protected function ipInRange(string $ip, string $range): bool
    {
        list($subnet, $bits) = explode('/', $range);
        $ip = ip2long($ip);
        $subnet = ip2long($subnet);
        $mask = -1 << (32 - $bits);
        $subnet &= $mask;
        return ($ip & $mask) == $subnet;
    }

    /**
     * Check IP reputation using external service or internal database
     *
     * NOT: Production'da IPQualityScore, MaxMind GeoIP2, IPHub gibi
     * servisler kullanılabilir. Şu an basit bir örnek implementasyon.
     */
    protected function checkIpReputation(string $ip): array
    {
        // Önce internal database'den kontrol et
        $internalCheck = $this->checkInternalDatabase($ip);
        if ($internalCheck) {
            return $internalCheck;
        }

        // Daha sonra external service kullanılabilir
        // Örnek: return $this->checkExternalService($ip);

        // Default: temiz IP
        return [
            'service' => 'internal',
            'is_vpn' => false,
            'is_proxy' => false,
            'is_tor' => false,
            'is_datacenter' => false,
            'risk_score' => 0,
            'country_code' => null,
            'city' => null,
        ];
    }

    /**
     * Check internal fraud database
     */
    protected function checkInternalDatabase(string $ip): ?array
    {
        // TODO: Internal blacklist/whitelist database
        // Örnek: fraud_ip_blacklist tablosundan kontrol

        return null;
    }

    /**
     * Check external reputation service (örnek)
     *
     * Production'da kullanılabilecek servisler:
     * - IPQualityScore: https://www.ipqualityscore.com/
     * - MaxMind GeoIP2: https://www.maxmind.com/
     * - IPHub: https://iphub.info/
     * - IP2Location: https://www.ip2location.com/
     */
    protected function checkExternalService(string $ip): array
    {
        // Örnek implementasyon - gerçek API key ile kullanılmalı
        /*
        try {
            $response = Http::timeout(5)->get('https://ipqualityscore.com/api/json/ip', [
                'key' => config('services.ipqs.key'),
                'ip' => $ip,
            ]);

            if ($response->successful()) {
                $data = $response->json();
                return [
                    'service' => 'ipqualityscore',
                    'is_vpn' => $data['vpn'] ?? false,
                    'is_proxy' => $data['proxy'] ?? false,
                    'is_tor' => $data['tor'] ?? false,
                    'is_datacenter' => $data['is_crawler'] ?? false,
                    'risk_score' => $data['fraud_score'] ?? 0,
                    'country_code' => $data['country_code'] ?? null,
                    'city' => $data['city'] ?? null,
                ];
            }
        } catch (\Exception $e) {
            \Log::warning('IP reputation check failed: ' . $e->getMessage());
        }
        */

        return [
            'service' => 'none',
            'is_vpn' => false,
            'is_proxy' => false,
            'is_tor' => false,
            'is_datacenter' => false,
            'risk_score' => 0,
        ];
    }
}
