<?php

namespace App\Services;

use App\Util;

class PagYeepPay
{
    public $config;
    public $key;
    public $orgNo;
    public $custId;
    public $apiUrl;

    public function __construct()
    {
        $payConfigService = new PayConfig();
        $this->config = $payConfigService->getConfig('PagYeepPay');
        
        $this->key = $this->config['key'] ?? '';
//        $this->orgNo = $this->config['orgNo'] ?? '';
//        $this->custId = $this->config['custId'] ?? '';
        $this->apiUrl = $this->config['apiUrl'] ?? '';
    }

    /**
     * 签名 - PagYeepPay专用签名算法
     * 
     * 规则（根据文档）：
     * 1. 按参数名ASCII码从小到大排序（字典序）
     * 2. 空值不参与签名
     * 3. sign参数不参与签名
     * 4. 拼接格式：key1=value1&key2=value2&key=商户密钥
     * 5. 参数值使用原始值，不进行URL Encode
     * 6. MD5后转大写
     */
    public function sign(array $params): array
    {
        // 移除sign和空值
        $signParams = [];
        foreach ($params as $key => $value) {
            if ($key !== 'sign' && $value !== null && $value !== '') {
                $signParams[$key] = $value;
            }
        }
        
        // 按ASCII码排序
        ksort($signParams);
        
        // 拼接字符串：key1=value1&key2=value2（不进行URL Encode）
        $stringA = '';
        foreach ($signParams as $key => $value) {
            if ($stringA !== '') {
                $stringA .= '&';
            }
            $stringA .= $key . '=' . $value;
        }
        
        // 拼接商户密钥：stringA&key=商户密钥
        $stringSignTemp = $stringA . '&key=' . $this->key;
        
        // MD5并转大写
        $sign = strtoupper(md5($stringSignTemp));
        
        // 将签名添加到参数中
        $params['sign'] = $sign;
        
        Util::WriteLog('PagYeepPay_sign', "待签名字符串: " . $stringSignTemp);
        Util::WriteLog('PagYeepPay_sign', "签名结果: " . $sign);
        
        return $params;
    }

    /**
     * 验签 - PagYeepPay专用验签算法
     */
    public function verifySign(array $params): bool
    {
        if (!isset($params['sign'])) {
            return false;
        }
        
        $receivedSign = $params['sign'];
        
        // 移除sign和空值
        $signParams = [];
        foreach ($params as $key => $value) {
            if ($key !== 'sign' && $value !== null && $value !== '') {
                $signParams[$key] = $value;
            }
        }
        
        // 按ASCII码排序
        ksort($signParams);
        
        // 拼接字符串（不进行URL Encode）
        $stringA = '';
        foreach ($signParams as $key => $value) {
            if ($stringA !== '') {
                $stringA .= '&';
            }
            $stringA .= $key . '=' . $value;
        }
        
        // 拼接商户密钥
        $stringSignTemp = $stringA . '&key=' . $this->key;
        
        // MD5并转大写
        $calculatedSign = strtoupper(md5($stringSignTemp));
        
        Util::WriteLog('PagYeepPay_verify', "待验签字符串: " . $stringSignTemp);
        Util::WriteLog('PagYeepPay_verify', "计算签名: " . $calculatedSign);
        Util::WriteLog('PagYeepPay_verify', "接收签名: " . $receivedSign);
        
        return $calculatedSign === $receivedSign;
    }

    /**
     * POST请求 - application/x-www-form-urlencoded
     */
    public function curlPost($url, $payload)
    {
        $timeout = 20;
        
        // PagYeepPay使用 application/x-www-form-urlencoded 格式，UTF-8编码
        $data = http_build_query($payload, '', '&', PHP_QUERY_RFC3986);
        
        $headers = [
            'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if (curl_errno($ch)) {
            $error = curl_error($ch);
            Util::WriteLog('PagYeepPay_error', 'CURL Error: ' . $error);
            curl_close($ch);
            return false;
        }

        if ($httpCode != 200) {
            Util::WriteLog('PagYeepPay_error', 'HTTP Code: ' . $httpCode . " | Response: " . $result);
        }

        curl_close($ch);
        return $result;
    }
}
