<?php
/**
 * 加载站点 check_config 配置（define 常量）
 */
class ConfigLoader
{
    public static function loadFile($configFile)
    {
        if (file_exists($configFile)) {
            include $configFile;
        }
    }

    /**
     * @return string 实际加载的配置名
     */
    public static function loadByName($configName, $baseDir = null)
    {
        $baseDir    = $baseDir ?: dirname(__DIR__);
        $configName = self::sanitizeConfigName($configName);
        $configFile = $baseDir . '/check_config/' . $configName . '_config.php';
        if (file_exists($configFile)) {
            self::loadFile($configFile);
            return $configName;
        }
        self::loadFile($baseDir . '/check_config/index_config.php');
        return 'index';
    }

    /**
     * @return string 实际加载的配置名
     */
    public static function loadByHost($host, $baseDir = null)
    {
        $baseDir = $baseDir ?: dirname(__DIR__);
        if (!class_exists('DomainRepository', false)) {
            require_once dirname(__DIR__) . '/lib/Cloak/DomainRepository.php';
        }
        $name = DomainRepository::resolveConfigNameForHost((string) $host, $baseDir);
        return self::loadByName($name, $baseDir);
    }

    /**
     * 同域多落地页：入口脚本有独立配置时优先脚本名；
     * 伪静态/rewrite 落到 index.php 时从 REQUEST_URI 路径解析配置名；
     * 否则按 HTTP Host（多站/宝塔）；再回退脚本名或 index
     *
     * @return string 实际加载的配置名
     */
    public static function loadForRequest($scriptBaseName, $host = null)
    {
        $host = $host ?? ($_SERVER['HTTP_HOST'] ?? '');
        $baseDir = dirname(__DIR__);
        $scriptSanitized = self::sanitizeConfigName((string) $scriptBaseName);
        if (self::hasConfigFile($scriptSanitized, $baseDir)) {
            return self::loadByName($scriptSanitized);
        }

        $uriConfigName = self::resolveConfigNameFromRequestUri($baseDir);
        if ($uriConfigName !== null) {
            return self::loadByName($uriConfigName);
        }

        if ($host !== '') {
            return self::loadByHost($host);
        }
        if ($scriptBaseName !== null && $scriptBaseName !== '') {
            return self::loadByName($scriptBaseName);
        }
        return self::loadByName('index');
    }

    /**
     * 从 URL 或路径解析落地页配置名（不含 query）。
     *
     * @return string|null
     */
    public static function resolveConfigNameFromUrl($url, $baseDir = null)
    {
        if ($url === '') {
            return null;
        }
        $path = parse_url($url, PHP_URL_PATH);
        if (!is_string($path)) {
            return null;
        }
        return self::resolveConfigNameFromPath($path, $baseDir);
    }

    /**
     * 从 REQUEST_URI 路径段解析落地页配置名（不含 query）。
     * 用于 nginx try_files → index.php 等场景：/PH-fwa037?utm=... 仍应对应 PH-fwa037 配置。
     *
     * @return string|null 可加载的配置名；无法解析时 null
     */
    public static function resolveConfigNameFromRequestUri($baseDir = null)
    {
        $uri = (string) ($_SERVER['REQUEST_URI'] ?? '');
        if ($uri === '') {
            return null;
        }
        $path = parse_url($uri, PHP_URL_PATH);
        if (!is_string($path)) {
            return null;
        }
        return self::resolveConfigNameFromPath($path, $baseDir);
    }

    /**
     * @return string|null
     */
    public static function resolveConfigNameFromPath($path, $baseDir = null)
    {
        $baseDir = $baseDir ?: dirname(__DIR__);
        $path = (string) $path;
        if ($path === '' || $path === '/') {
            return null;
        }

        $basename = basename($path);
        $name = self::sanitizeConfigName($basename);
        if ($name === 'index' || $name === 'ip_check' || $name === 'f_check') {
            return null;
        }
        if (!self::hasConfigFile($name, $baseDir)) {
            return null;
        }
        return $name;
    }

    /**
     * 二次风控 f_check / byApiRisk：优先 hdata.config_name，其次落地页 URL 路径，再 Host 映射。
     *
     * @param string      $pageUrl           hdata.domain（浏览器当前页完整 URL）
     * @param string|null $fallbackHost      兜底 Host（通常为 HTTP_HOST）
     * @param string|null $explicitConfigName hdata.config_name（ip_check 阶段已解析的配置名）
     * @return string 实际加载的配置名
     */
    public static function loadForFingerprint($pageUrl, $fallbackHost = null, $explicitConfigName = null)
    {
        $baseDir = dirname(__DIR__);

        if ($explicitConfigName !== null && trim((string) $explicitConfigName) !== '') {
            $explicit = self::sanitizeConfigName($explicitConfigName);
            if (self::hasConfigFile($explicit, $baseDir)) {
                return self::loadByName($explicit, $baseDir);
            }
        }

        $fromUrl = self::resolveConfigNameFromUrl((string) $pageUrl, $baseDir);
        if ($fromUrl !== null) {
            return self::loadByName($fromUrl, $baseDir);
        }

        $host = $fallbackHost ?? ($_SERVER['HTTP_HOST'] ?? '');
        if ($host !== '') {
            return self::loadByHost($host, $baseDir);
        }

        return self::loadByName('index', $baseDir);
    }

    /**
     * @param string $configName
     */
    private static function hasConfigFile($configName, $baseDir)
    {
        $configName = self::sanitizeConfigName($configName);
        if ($configName === 'index' || $configName === 'ip_check') {
            return false;
        }
        return file_exists($baseDir . '/check_config/' . $configName . '_config.php');
    }

    public static function sanitizeConfigName($name)
    {
        $name = trim((string) $name);
        $name = str_replace('.php', '', $name);
        if ($name === '' || !preg_match('/^[a-zA-Z0-9_-]+$/', $name)) {
            return 'index';
        }
        return $name;
    }
}
