<?php
/**
 * StablePay API 客户端
 *
 * @package StablePay_WooCommerce
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

/**
 * StablePay_API_Client 类
 *
 * 封装 StablePay API 调用逻辑，包括签名生成、请求发送、错误处理
 */
class StablePay_API_Client {
    /**
     * API 基础 URL（生产环境）
     */
    const API_BASE_URL_PRODUCTION = 'https://api.stablepay.co';

    /**
     * API 基础 URL（预发环境）
     */
    const API_BASE_URL_STAGING = 'https://api-staging.stablepay.co';

    /**
     * API 基础 URL（测试环境）
     */
    const API_BASE_URL_DEV = 'https://api.wenfu.cn';

    /**
     * API 版本
     */
    const API_VERSION = '2024-01-01';

    /**
     * API Key
     *
     * @var string
     */
    private $api_key;

    /**
     * Secret Key
     *
     * @var string
     */
    private $secret_key;

    /**
     * 环境模式 (dev/staging/production)
     *
     * @var string
     */
    private $environment;

    /**
     * 日志记录器
     *
     * @var StablePay_Logger
     */
    private $logger;

    /**
     * 构造函数
     *
     * @param string $api_key API Key
     * @param string $secret_key Secret Key
     * @param string $environment 环境模式 (dev/staging/production)
     * @param StablePay_Logger $logger 日志记录器
     */
    public function __construct($api_key, $secret_key, $environment = 'production', $logger = null) {
        $this->api_key = $api_key;
        $this->secret_key = $secret_key;
        $this->environment = $environment;
        $this->logger = $logger ? $logger : new StablePay_Logger();
    }

    /**
     * 创建支付会话
     *
     * @param array $params 支付参数
     * @param array $extra_headers 额外的请求头（可选）
     * @return array|WP_Error API 响应或错误对象
     */
    public function create_checkout_session($params, $extra_headers = array()) {
        $this->logger->debug('API 客户端：创建支付会话', array(
            'order_id' => isset($params['order_id']) ? $params['order_id'] : null,
            'amount' => isset($params['amount']) ? $params['amount'] : null,
            'currency' => isset($params['currency']) ? $params['currency'] : null,
        ));
        $endpoint = '/api/v1/checkout/sessions/create';
        return $this->request('POST', $endpoint, $params, $extra_headers);
    }

    /**
     * 创建退款
     *
     * @param array $params 退款参数
     * @return array|WP_Error API 响应或错误对象
     */
    public function create_refund($params) {
        // 强制写入 error_log 便于调试
        error_log(sprintf('[StablePay] API create_refund: charge=%s, amount=%s, currency=%s',
            isset($params['charge']) ? $params['charge'] : 'null',
            isset($params['amount']) ? $params['amount'] : 'null',
            isset($params['currency']) ? $params['currency'] : 'null'));

        $this->logger->debug('API 客户端：创建退款', array(
            'charge' => isset($params['charge']) ? $params['charge'] : null,
            'refund_id' => isset($params['refund_id']) ? $params['refund_id'] : null,
            'amount' => isset($params['amount']) ? $params['amount'] : null,
            'currency' => isset($params['currency']) ? $params['currency'] : null,
        ));
        $endpoint = '/api/v1/refunds/create';
        return $this->request('POST', $endpoint, $params);
    }

    /**
     * 发送 API 请求
     *
     * @param string $method HTTP 方法
     * @param string $endpoint API 端点
     * @param array $body 请求体
     * @param array $extra_headers 额外的请求头（可选）
     * @return array|WP_Error API 响应或错误对象
     */
    private function request($method, $endpoint, $body = array(), $extra_headers = array()) {
        // 根据环境选择 API 基础 URL
        switch ($this->environment) {
            case 'dev':
                $base_url = self::API_BASE_URL_DEV;
                break;
            case 'staging':
                $base_url = self::API_BASE_URL_STAGING;
                break;
            default:
                $base_url = self::API_BASE_URL_PRODUCTION;
        }
        $url = $base_url . $endpoint;

        // 生成请求体 JSON
        $request_body = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

        // 生成时间戳和 Nonce
        $timestamp = time();
        $nonce = $this->generate_nonce();

        // 生成签名
        $signature = $this->generate_signature($timestamp, $nonce, $request_body);

        $this->logger->debug('生成请求签名', array(
            'endpoint' => $endpoint,
            'timestamp' => $timestamp,
            'nonce' => $nonce,
            'signature_length' => strlen($signature),
        ));

        // 构造请求头
        $headers = array(
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $this->api_key,
            'X-StablePay-Timestamp' => $timestamp,
            'X-StablePay-Nonce' => $nonce,
            'X-StablePay-Signature' => $signature,
            'StablePay-Version' => self::API_VERSION,
        );

        // 合并额外的请求头
        if (!empty($extra_headers)) {
            $headers = array_merge($headers, $extra_headers);
            $this->logger->debug('合并额外请求头', array(
                'extra_headers' => array_keys($extra_headers),
            ));
        }

        // 记录请求日志
        $this->logger->info('发送 API 请求', array(
            'method' => $method,
            'url' => $url,
            'endpoint' => $endpoint,
            'body_size' => strlen($request_body),
            'environment' => $this->environment,
        ));

        // 发送请求
        $start_time = microtime(true);
        $response = wp_remote_request($url, array(
            'method' => $method,
            'headers' => $headers,
            'body' => $request_body,
            'timeout' => 30,
            'sslverify' => true,
        ));
        $duration = round((microtime(true) - $start_time) * 1000);

        // 检查请求错误
        if (is_wp_error($response)) {
            $this->logger->error('API 请求失败（网络错误）', array(
                'endpoint' => $endpoint,
                'error_code' => $response->get_error_code(),
                'error_message' => $response->get_error_message(),
                'duration_ms' => $duration,
            ));
            return $response;
        }

        // 获取响应状态码和响应体
        $status_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        $response_headers = wp_remote_retrieve_headers($response);

        // 记录响应日志
        $this->logger->info('收到 API 响应', array(
            'endpoint' => $endpoint,
            'status_code' => $status_code,
            'duration_ms' => $duration,
            'response_size' => strlen($response_body),
        ));

        // 解析响应 JSON
        $data = json_decode($response_body, true);
        $json_error = json_last_error();

        if ($json_error !== JSON_ERROR_NONE) {
            $this->logger->error('API 响应 JSON 解析失败', array(
                'endpoint' => $endpoint,
                'json_error' => $json_error,
                'response_preview' => substr($response_body, 0, 200),
            ));
        }

        // 检查 HTTP 状态码（200 和 201 都表示成功）
        if ($status_code !== 200 && $status_code !== 201) {
            $error_message = $this->parse_error_response($data, $status_code);
            error_log(sprintf('[StablePay] API 返回错误: endpoint=%s, status=%d, error=%s', $endpoint, $status_code, $error_message));
            $this->logger->error('API 返回错误', array(
                'endpoint' => $endpoint,
                'status_code' => $status_code,
                'error' => $error_message,
                'response_body' => $response_body,
                'request_id' => isset($response_headers['x-request-id']) ? $response_headers['x-request-id'] : null,
            ));
            return new WP_Error('stablepay_api_error', $error_message, array('status' => $status_code));
        }

        error_log(sprintf('[StablePay] API 请求成功: endpoint=%s, status=%d', $endpoint, $status_code));
        $this->logger->debug('API 请求成功', array(
            'endpoint' => $endpoint,
            'response_keys' => is_array($data) ? array_keys($data) : null,
        ));

        return $data;
    }

    /**
     * 生成随机 Nonce
     *
     * @return string UUID 格式的 Nonce
     */
    private function generate_nonce() {
        return sprintf(
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }

    /**
     * 生成 HMAC-SHA256 签名
     *
     * @param int $timestamp 时间戳
     * @param string $nonce Nonce
     * @param string $request_body 请求体 JSON
     * @return string 签名（十六进制）
     */
    private function generate_signature($timestamp, $nonce, $request_body) {
        // 构造待签名字符串：timestamp.nonce.request_body
        $payload = $timestamp . '.' . $nonce . '.' . $request_body;

        // 计算 HMAC-SHA256 签名
        $signature = hash_hmac('sha256', $payload, $this->secret_key);

        return $signature;
    }

    /**
     * 解析错误响应
     *
     * @param array|null $data 响应数据
     * @param int $status_code HTTP 状态码
     * @return string 错误消息
     */
    private function parse_error_response($data, $status_code) {
        if (isset($data['error']['message'])) {
            return $data['error']['message'];
        }

        // 默认错误消息
        $default_messages = array(
            400 => '请求参数错误',
            401 => '认证失败，请检查 API 密钥',
            403 => '无权限访问',
            404 => '资源不存在',
            429 => '请求频率超限',
            500 => '服务器内部错误',
        );

        return isset($default_messages[$status_code])
            ? $default_messages[$status_code]
            : '未知错误';
    }

    /**
     * 验证 Webhook 签名
     *
     * @param string $signature 接收到的签名
     * @param int $timestamp 接收到的时间戳
     * @param string $body 原始请求体
     * @param string $webhook_secret Webhook 密钥
     * @return bool 签名是否有效
     */
    public static function verify_webhook_signature($signature, $timestamp, $body, $webhook_secret) {
        // 验证时间戳（5分钟有效期）
        $current_time = time();
        if (abs($current_time - intval($timestamp)) > 300) {
            return false;
        }

        // 计算期望签名：HMAC-SHA256(timestamp + "." + body, secret)
        $payload = $timestamp . '.' . $body;
        $expected_signature = hash_hmac('sha256', $payload, $webhook_secret);

        // 时间安全比较
        return hash_equals($expected_signature, $signature);
    }
}
