<?php

namespace App\Services\Apcopay;

use App\Services\PayConfig;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class ApcopayClient
{
    protected $client;
    protected $config;

    public function __construct()
    {
        $payConfigService = new PayConfig();
        $this->config =$payConfigService->getConfig('Apcopay');

        // 确保base_uri不重复包含/merchanttools
        $baseUrl = rtrim($this->config['api_url'], '/');
        // 如果baseUrl已经包含merchanttools,则移除它
        if (strpos($baseUrl, '/merchanttools') !== false) {
            $baseUrl = str_replace('/merchanttools', '', $baseUrl);
        }

        $this->client = new Client([
            'base_uri' => $baseUrl,
            'timeout' => 30,
            'verify' => false // 开发环境可能需要关闭SSL验证
        ]);

        // 记录初始化信息
        Log::info('Apcopay Client initialized', [
            'base_uri' => $baseUrl,
            'config' => $this->config
        ]);
    }

    /**
     * 生成Basic认证头
     */
    protected function getAuthorizationHeader(): string
    {
        $credentials = base64_encode($this->config['client_id'] . ':' . $this->config['secret_key']);
        return 'Basic ' . $credentials;
    }

    /**
     * 生成签名
     */
    protected function generateSignature(array $data): string
    {
        // 记录签名前的数据
        Log::info('Apcopay Signature Data Before', [
            'data' => $data
        ]);

        // 使用品牌密钥 - 直接使用，不做解码
        $brandKey = $this->config['brand_key'];

        // 1. 扁平化并按字母顺序排序字段
        $fields = $this->flattenAndSortFields($data);

        // 记录扁平化后的字段
        Log::info('Apcopay Flattened Fields', [
            'fields' => $fields
        ]);

        // 2. 拼接字段
        $fieldsString = $this->concatenateFields($fields);

        // 记录拼接后的字符串
        Log::info('Apcopay Concatenated Fields', [
            'fieldsString' => $fieldsString
        ]);

        // 3. 转为小写
        $lowercaseString = strtolower($fieldsString);

        Log::info('Apcopay Lowercase String', [
            'lowercaseString' => $lowercaseString
        ]);

        // 4. 使用HMAC SHA256计算签名
        Log::info('Apcopay Brand Key Length', [
            'length' => strlen($brandKey)
        ]);

        // 生成签名
        $signature = base64_encode(hash_hmac('sha256', $lowercaseString, $brandKey, true));

        // 记录生成的签名
        Log::info('Apcopay Generated Signature', [
            'signature' => $signature
        ]);

        return $signature;
    }

    /**
     * 扁平化并排序字段 - 完全按照官方文档实现
     */
    protected function flattenAndSortFields(array $data, string $prefix = ''): array
    {
        $fields = [];

        foreach ($data as $key => $value) {
            $fieldKey = $prefix ? "{$prefix}.{$key}" : $key;

            if (is_null($value)) {
                $fields[$fieldKey] = '';
            } elseif (is_array($value)) {
                // 检查是否为索引数组
                if (array_keys($value) === range(0, count($value) - 1)) {
                    // 索引数组处理方式
                    foreach ($value as $index => $item) {
                        $arrayKey = $fieldKey . "[" . $index . "]";
                        if (is_array($item)) {
                            $fields = array_merge($fields, $this->flattenAndSortFields($item, $arrayKey));
                        } else {
                            $fields[$arrayKey] = $this->formatValue($item);
                        }
                    }
                } else {
                    // 关联数组处理方式
                    $fields = array_merge($fields, $this->flattenAndSortFields($value, $fieldKey));
                }
            } else {
                $fields[$fieldKey] = $this->formatValue($value);
            }
        }

        ksort($fields, SORT_STRING | SORT_FLAG_CASE);
        return $fields;
    }

    /**
     * 处理布尔值转字符串 - 确保与官方文档一致
     */
    protected function formatValue($value)
    {
        if (is_bool($value)) {
            return $value ? 'true' : 'false';
        } elseif (is_null($value)) {
            return '';
        }

        return (string)$value;
    }

    /**
     * 拼接字段
     */
    protected function concatenateFields(array $fields): string
    {
        $pairs = [];
        foreach ($fields as $key => $value) {
            $pairs[] = $key . '=' . $value;
        }
        return implode('&', $pairs);
    }

    /**
     * 发送请求
     */
    protected function request(string $method, string $uri, array $data = [], array $headers = []): array
    {
        try {
            // 记录请求信息
            Log::info('Apcopay API Request', [
                'method' => $method,
                'uri' => $uri,
                'data' => $data
            ]);

            // 生成签名
            $signature = $this->generateSignature($data);

            // 1. 准备请求头
            $headers = array_merge([
                'Authorization' => $this->getAuthorizationHeader(),
                'User-Agent' => 'PHP/ApcopayAPI',
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'Signature' => $signature  // 添加签名到请求头
            ], $headers);

            // 2. 不再将签名添加到请求体中，按照文档仅添加到请求头

            // 记录完整请求头和请求体
            Log::info('Apcopay API Request Details', [
                'headers' => array_merge(
                    $headers,
                    ['Authorization' => 'Basic **REDACTED**'] // 不记录完整的Authorization头
                ),
                'data' => $data
            ]);

            // 3. 发送请求
            $options = [
                'headers' => $headers,
                'http_errors' => false // 不自动抛出HTTP错误，我们自己处理
            ];

            if (!empty($data)) {
                $options['json'] = $data;
            }

            $response = $this->client->request($method, $uri, $options);

            // 3. 解析响应
            $statusCode = $response->getStatusCode();
            $body = $response->getBody()->getContents();

            Log::info('Apcopay API Raw Response', [
                'uri' => $uri,
                'status_code' => $statusCode,
                'body' => $body
            ]);

            $result = json_decode($body, true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                Log::error('Apcopay API Invalid JSON', [
                    'uri' => $uri,
                    'body' => $body,
                    'json_error' => json_last_error_msg()
                ]);
                throw new \RuntimeException('Invalid JSON response: ' . $body);
            }

            // 4. 检查HTTP状态码
            if ($statusCode >= 400) {
                Log::error('Apcopay API HTTP Error', [
                    'uri' => $uri,
                    'status_code' => $statusCode,
                    'result' => $result
                ]);

                // 返回错误信息而不是抛出异常，让调用者决定如何处理
                return [
                    'isSuccess' => false,
                    'errorMessage' => $result['errorMessage'] ?? "HTTP Error: {$statusCode}",
                    'statusCode' => $statusCode,
                    'rawResponse' => $result
                ];
            }

            // 记录响应信息
            Log::info('Apcopay API Response', [
                'uri' => $uri,
                'result' => $result
            ]);

            return $result;

        } catch (GuzzleException $e) {
            Log::error('Apcopay API Error', [
                'method' => $method,
                'uri' => $uri,
                'data' => $data,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return [
                'isSuccess' => false,
                'errorMessage' => 'Apcopay API request failed: ' . $e->getMessage(),
                'exception' => get_class($e)
            ];
        } catch (\Exception $e) {
            Log::error('Apcopay General Error', [
                'method' => $method,
                'uri' => $uri,
                'data' => $data,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return [
                'isSuccess' => false,
                'errorMessage' => 'Error processing Apcopay request: ' . $e->getMessage(),
                'exception' => get_class($e)
            ];
        }
    }

    /**
     * GET请求
     */
    protected function get(string $uri, array $query = [], array $headers = []): array
    {
        return $this->request('GET', $uri . '?' . http_build_query($query), [], $headers);
    }

    /**
     * POST请求
     */
    protected function post(string $uri, array $data = [], array $headers = []): array
    {
        return $this->request('POST', $uri, $data, $headers);
    }

    /**
     * PUT请求
     */
    protected function put(string $uri, array $data = [], array $headers = []): array
    {
        return $this->request('PUT', $uri, $data, $headers);
    }

    /**
     * DELETE请求
     */
    protected function delete(string $uri, array $headers = []): array
    {
        return $this->request('DELETE', $uri, [], $headers);
    }
}
