<?php
/**
* 高性能HTTP请求类 - PHP 5.6+ 兼容版本
*/

// 安全检查
if (!defined('INCLUDE_PATH')) {
    die('禁止直接访问');
}

class RemoteDataFetcher {
    private $timeout = 30;
    private $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36';
    private $headers = [];
    private $lastError = [];
    private $lastResponseCode = 0;
    private $lastRequestInfo = [];

    public function setTimeout($seconds) {
        $this->timeout = max(1, (int)$seconds);
        return $this;
    }

    public function setUserAgent($ua) {
        $this->userAgent = $ua;
        return $this;
    }

    public function addHeader($header) {
        $this->headers[] = $header;
        return $this;
    }

    public function setHeaders(array $headers) {
        $this->headers = $headers;
        return $this;
    }

    public function getLastError() {
        return $this->lastError;
    }

    public function getLastResponseCode() {
        return $this->lastResponseCode;
    }

    public function getLastRequestInfo() {
        return $this->lastRequestInfo;
    }

    /**
    * 发送GET请求
    */
    public function get($url, $params = []) {
        if (!empty($params)) {
            $url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($params);
        }
        return $this->request($url, 'GET');
    }

    /**
    * 发送POST请求
    */
    public function post($url, $data = [], $isJson = false) {
        $options = [];
        if ($isJson) {
            $this->addHeader('Content-Type: application/json');
            $options['post_data'] = json_encode($data);
        } else {
            $options['post_data'] = http_build_query($data);
        }
        return $this->request($url, 'POST', $options);
    }

    /**
    * 设置错误信息
    */
    private function setError($type, $message, $code = 0, $details = []) {
        $this->lastError = [
            'type' => $type,
            'message' => $message,
            'code' => $code,
            'timestamp' => date('Y-m-d H:i:s'),
            'details' => $details
        ];
    }

    /**
    * 清除错误信息
    */
    public function clearError() {
        $this->lastError = [];
    }

    /**
    * 检查是否有错误
    */
    public function hasError() {
        return !empty($this->lastError);
    }

    /**
    * 执行HTTP请求 - 增强错误处理
    */
    private function request($url, $method = 'GET', $options = []) {
        $this->clearError();
        $this->lastResponseCode = 0;
        $this->lastRequestInfo = [];

        // URL验证
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            $this->setError('INVALID_URL', '无效的URL地址', 400, ['url' => $url]);
            return false;
        }

        // 检查cURL扩展
        if (!function_exists('curl_init')) {
            $this->setError('CURL_NOT_AVAILABLE', 'cURL扩展未安装', 500);
            return false;
        }

        $ch = curl_init();

        // 基础cURL配置
        $curl_options = [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_USERAGENT => $this->userAgent,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 5,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HEADER => false,
            CURLOPT_ENCODING => 'gzip'
        ];

        // 添加自定义头部
        if (!empty($this->headers)) {
            $curl_options[CURLOPT_HTTPHEADER] = $this->headers;
        }

        // 根据请求方法设置选项
        switch (strtoupper($method)) {
            case 'POST':
                $curl_options[CURLOPT_POST] = true;
                if (isset($options['post_data'])) {
                    $curl_options[CURLOPT_POSTFIELDS] = $options['post_data'];
                }
                break;
            case 'PUT':
                $curl_options[CURLOPT_CUSTOMREQUEST] = 'PUT';
                if (isset($options['post_data'])) {
                    $curl_options[CURLOPT_POSTFIELDS] = $options['post_data'];
                }
                break;
            case 'DELETE':
                $curl_options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
                break;
            default:
                $curl_options[CURLOPT_HTTPGET] = true;
                break;
        }

        // 设置cURL选项
        if (!curl_setopt_array($ch, $curl_options)) {
            $this->setError('CURL_OPTION_ERROR', '设置cURL选项失败', 500);
            curl_close($ch);
            return false;
        }

        // 执行请求
        $response = curl_exec($ch);
        $this->lastResponseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        // 记录请求信息
        $this->lastRequestInfo = [
            'url' => $url,
            'method' => $method,
            'http_code' => $this->lastResponseCode,
            'total_time' => curl_getinfo($ch, CURLINFO_TOTAL_TIME),
            'size_download' => curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD),
            'connect_time' => curl_getinfo($ch, CURLINFO_CONNECT_TIME),
            'namelookup_time' => curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME)
        ];

        // 检查cURL错误
        if (curl_errno($ch)) {
            $errorDetails = [
                'curl_error_no' => curl_errno($ch),
                'curl_error' => curl_error($ch),
                'url' => $url,
                'method' => $method,
                'http_code' => $this->lastResponseCode
            ];

            $this->setError('CURL_ERROR', 'cURL请求失败: ' . curl_error($ch), curl_errno($ch), $errorDetails);

            curl_close($ch);
            return false;
        }

        curl_close($ch);

        // 检查HTTP错误
        if ($this->lastResponseCode >= 400) {
            $this->setError('HTTP_ERROR', 'HTTP请求失败: ' . $this->lastResponseCode, $this->lastResponseCode, [
                'url' => $url,
                'method' => $method,
                'http_code' => $this->lastResponseCode,
                'response' => substr($response, 0, 500)
            ]);
            return false;
        }

        return $response;
    }

    /**
    * 批量请求 - 新增功能
    */
    public function multiRequest($urls, $concurrent = 5) {
        if (!is_array($urls) || empty($urls)) {
            $this->setError('INVALID_URLS', 'URL列表为空或无效', 400);
            return false;
        }

        $mh = curl_multi_init();
        $handles = [];
        $results = [];

        // 初始化所有cURL句柄
        foreach ($urls as $i => $url) {
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => $this->timeout,
                CURLOPT_USERAGENT => $this->userAgent,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 3,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false
            ]);
            
            $handles[$i] = $ch;
            curl_multi_add_handle($mh, $ch);
        }

        // 执行多请求
        $running = null;
        do {
            curl_multi_exec($mh, $running);
            curl_multi_select($mh);
        } while ($running > 0);

        // 获取结果
        foreach ($handles as $i => $ch) {
            $results[$i] = curl_multi_getcontent($ch);
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }

        curl_multi_close($mh);
        return $results;
    }

    /**
    * 检查URL是否可达 - 新增功能
    */
    public function checkUrl($url, $timeout = 5) {
        $originalTimeout = $this->timeout;
        $this->setTimeout($timeout);
        
        $result = $this->head($url);
        $this->setTimeout($originalTimeout);
        
        return $this->lastResponseCode === 200;
    }

    /**
    * HEAD请求 - 新增功能
    */
    public function head($url) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_NOBODY => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_USERAGENT => $this->userAgent,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER => false
        ]);

        $response = curl_exec($ch);
        $this->lastResponseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        curl_close($ch);
        return $response !== false;
    }
}
?>