<?php

namespace App\Services;

use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;

/**
 * IP风险检测服务
 *
 * 检测逻辑：
 * 1. 通过 ip-api.com 获取 IP 的 ASN 和国家信息
 * 2. 如果 ASN/ISP 关键字包含常见云厂商 → 标记为可疑
 * 3. 如果 IP 不属于美国 → 标记为可疑
 */
class IpRiskService
{
    // 常见云厂商 ASN/ISP 关键字（小写）
    const CLOUD_KEYWORDS = [
        'amazon',
        'aws',
        'google cloud',
        'gcp',
        'microsoft azure',
        'microsoft corporation',
        'digitalocean',
        'linode',
        'vultr',
        'alibaba',
        'tencent',
        'oracle cloud',
        'ovh',
        'hetzner',
        'cloudflare',
        'akamai',
        'fastly',
    ];

    /**
     * 检测 IP 是否存在风险
     *
     * @param string $ip
     * @return array{is_risky: bool, reason: string, ip: string}
     */
    public function detect($ip)
    {
        $result = ['is_risky' => false, 'reason' => '', 'ip' => $ip];

        if (empty($ip) || $ip === '127.0.0.1' || $ip === '::1') {
            return $result;
        }

        // 私有 IP 范围不检测
        if ($this->isPrivateIp($ip)) {
            return $result;
        }

        $info = $this->queryIpInfo($ip);
        if (empty($info)) {
            return $result;
        }

        $countryCode = strtoupper($info['countryCode'] ?? '');
        $as = strtolower($info['as'] ?? '');
        $org = strtolower($info['org'] ?? '');
        $isp = strtolower($info['isp'] ?? '');

        $combined = $as . ' ' . $org . ' ' . $isp;

        // 检测1: 云厂商 ASN/ISP 关键字
        $matchedKeyword = $this->matchCloudKeyword($combined);
        if ($matchedKeyword) {
            $result['is_risky'] = true;
            $result['reason'] = "cloud_asn:{$matchedKeyword}";
            Log::info("IpRisk: cloud ASN detected", ['ip' => $ip, 'keyword' => $matchedKeyword]);
            return $result;
        }

        // 检测2: 非美国 IP
        if ($countryCode !== '' && $countryCode !== 'US') {
            $result['is_risky'] = true;
            $result['reason'] = "non_us:{$countryCode}";
            Log::info("IpRisk: non-US IP detected", ['ip' => $ip, 'country' => $countryCode]);
            return $result;
        }

        return $result;
    }

    /**
     * 调用 ip-api.com 查询 IP 信息
     *
     * @param string $ip
     * @return array|null
     */
    protected function queryIpInfo($ip)
    {
        try {
            $client = new Client(['timeout' => 5]);
            $response = $client->get("http://ip-api.com/json/{$ip}", [
                'query' => ['fields' => 'countryCode,as,org,isp'],
            ]);
            $data = json_decode($response->getBody()->getContents(), true);

            if (isset($data['status']) && $data['status'] === 'fail') {
                Log::warning("IpRisk: ip-api query failed", ['ip' => $ip, 'msg' => $data['message'] ?? '']);
                return null;
            }

            return $data;
        } catch (\Exception $e) {
            Log::warning("IpRisk: ip-api request error", ['ip' => $ip, 'error' => $e->getMessage()]);
            return null;
        }
    }

    /**
     * 检查是否命中云厂商关键字
     *
     * @param string $text
     * @return string|false 命中的关键字，或 false
     */
    protected function matchCloudKeyword($text)
    {
        foreach (self::CLOUD_KEYWORDS as $keyword) {
            if (strpos($text, $keyword) !== false) {
                return $keyword;
            }
        }
        return false;
    }

    /**
     * 判断是否为私有 IP
     *
     * @param string $ip
     * @return bool
     */
    protected function isPrivateIp($ip)
    {
        return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false;
    }
}
