<?php
require_once __DIR__ . '/ClientIpResolver.php';

/**
 * IP 白名单与链接参数白名单判定（供流水线早期快速路径与黑白名单阶段复用）
 */
class WhitelistGate
{
    /**
     * @return string[]
     */
    public static function getWhitelistIps()
    {
        if (defined('WHITELIST_GROUP_ID') && (int) WHITELIST_GROUP_ID > 0) {
            return ip_group_list_addresses((int) WHITELIST_GROUP_ID);
        }
        if (!defined('SHOW_SITE_IP') || SHOW_SITE_IP === '') {
            return [];
        }

        return array_values(array_filter(array_map('trim', explode(',', SHOW_SITE_IP)), static function ($v) {
            return $v !== '';
        }));
    }

    /**
     * @param string $ip
     */
    public static function matchesWhitelistIp($ip)
    {
        $ip = trim((string) $ip);
        if ($ip === '') {
            return false;
        }

        foreach (self::getWhitelistIps() as $entry) {
            if (function_exists('ip_visitor_matches_list_entry') && ip_visitor_matches_list_entry($ip, $entry)) {
                return true;
            }
            if ($ip === $entry) {
                return true;
            }
        }

        return false;
    }

    public static function matchesWhitelistParams()
    {
        if (!defined('WHITE_PARAMS') || WHITE_PARAMS === '') {
            return false;
        }
        $wparams = explode('=', WHITE_PARAMS, 2);
        if (count($wparams) !== 2) {
            return false;
        }
        $pk = $wparams[0];
        $pv = $wparams[1];

        return isset($_GET[$pk]) && strip_tags((string) $_GET[$pk]) === $pv;
    }

    /**
     * @param visitorInfo|object|null $v_info
     */
    public static function resolveVisitorIp($v_info = null)
    {
        $ip = '';
        if ($v_info !== null && isset($v_info->v_ip)) {
            $ip = (string) $v_info->v_ip;
        }
        if ($ip === '' || $ip === '0.0.0.0') {
            $ip = ClientIpResolver::resolve();
        }
        return $ip;
    }

    /**
     * @param visitorInfo|object|null $v_info
     */
    public static function isMatched($v_info = null)
    {
        if (self::matchesWhitelistParams()) {
            return true;
        }

        return self::matchesWhitelistIp(self::resolveVisitorIp($v_info));
    }

    /**
     * 优先级：链接参数白名单 > IP 白名单
     *
     * @param visitorInfo|object|null $v_info
     */
    public static function matchReason($v_info = null)
    {
        if (self::matchesWhitelistParams()) {
            return '白名单链接参数';
        }
        if (self::matchesWhitelistIp(self::resolveVisitorIp($v_info))) {
            return '白名单';
        }

        return '白名单';
    }
}
