using System.Text.Json;
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Auth;
using HoneyBox.Model.Models.Payment;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace HoneyBox.Core.Services;

/// <summary>
/// 微信服务实现
/// </summary>
public class WechatService : IWechatService
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<WechatService> _logger;
    private readonly WechatPaySettings _wechatPaySettings;
    private readonly IRedisService _redisService;
    private readonly HoneyBoxDbContext _dbContext;
    private readonly IWechatPayConfigService? _wechatPayConfigService;

    // 微信API端点
    private const string WechatCodeToSessionUrl = "https://api.weixin.qq.com/sns/jscode2session";
    private const string WechatGetPhoneNumberUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";
    private const string WechatGetAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
    private const string WechatGetWxaCodeUnlimitUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";

    // Redis缓存键前缀
    private const string AccessTokenCacheKeyPrefix = "wechat:access_token:";

    public WechatService(
        HttpClient httpClient, 
        ILogger<WechatService> logger, 
        IOptions<WechatPaySettings> wechatPaySettings,
        IRedisService redisService,
        HoneyBoxDbContext dbContext,
        IWechatPayConfigService? wechatPayConfigService = null)
    {
        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _wechatPaySettings = wechatPaySettings?.Value ?? throw new ArgumentNullException(nameof(wechatPaySettings));
        _redisService = redisService ?? throw new ArgumentNullException(nameof(redisService));
        _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
        _wechatPayConfigService = wechatPayConfigService;
    }

    /// <summary>
    /// 获取微信openid和unionid
    /// </summary>
    public async Task<WechatAuthResult> GetOpenIdAsync(string code)
    {
        _logger.LogInformation("[微信登录] 开始处理，code={Code}", code);
        
        if (string.IsNullOrWhiteSpace(code))
        {
            _logger.LogWarning("[微信登录] code为空");
            return new WechatAuthResult
            {
                Success = false,
                ErrorMessage = "授权code不能为空"
            };
        }

        try
        {
            // 从数据库获取微信配置
            var wechatConfig = await GetWechatSettingFromDbAsync();
            if (wechatConfig == null)
            {
                _logger.LogError("[微信登录] 未找到小程序配置，请在后台管理系统中配置 miniprogram_setting");
                return new WechatAuthResult
                {
                    Success = false,
                    ErrorMessage = "小程序配置未设置，请联系管理员"
                };
            }
            
            var appId = wechatConfig.AppId;
            var appSecret = wechatConfig.AppSecret;
            
            // 记录配置信息（脱敏）
            var maskedAppId = appId?.Length > 8 
                ? $"{appId.Substring(0, 4)}****{appId.Substring(appId.Length - 4)}" 
                : "未配置";
            var maskedSecret = string.IsNullOrEmpty(appSecret) 
                ? "未配置" 
                : $"{appSecret.Substring(0, 4)}****";
            _logger.LogInformation("[微信登录] 配置信息: AppId={AppId}, AppSecret={AppSecret}, 来源=数据库", 
                maskedAppId, maskedSecret);
            
            var url = $"{WechatCodeToSessionUrl}?appid={appId}&secret={appSecret}&js_code={code}&grant_type=authorization_code";
            
            _logger.LogInformation("[微信登录] 调用微信API: {Url}", WechatCodeToSessionUrl);
            
            var response = await _httpClient.GetAsync(url);
            var content = await response.Content.ReadAsStringAsync();
            
            _logger.LogInformation("[微信登录] 微信API响应状态码: {StatusCode}", response.StatusCode);
            _logger.LogInformation("[微信登录] 微信API响应内容: {Content}", content);

            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError("[微信登录] 微信API返回HTTP错误 {StatusCode}: {Content}", response.StatusCode, content);
                return new WechatAuthResult
                {
                    Success = false,
                    ErrorMessage = "微信API调用失败"
                };
            }

            using var jsonDoc = JsonDocument.Parse(content);
            var root = jsonDoc.RootElement;

            // 检查是否有错误
            if (root.TryGetProperty("errcode", out var errCode) && errCode.GetInt32() != 0)
            {
                var errMsg = root.TryGetProperty("errmsg", out var msg) ? msg.GetString() : "未知错误";
                _logger.LogWarning("[微信登录] 微信API返回业务错误: errcode={ErrorCode}, errmsg={ErrorMessage}", errCode.GetInt32(), errMsg);
                return new WechatAuthResult
                {
                    Success = false,
                    ErrorMessage = $"微信授权失败: {errMsg}"
                };
            }

            // 提取openid和unionid
            var openId = root.TryGetProperty("openid", out var openIdProp) ? openIdProp.GetString() : null;
            var unionId = root.TryGetProperty("unionid", out var unionIdProp) ? unionIdProp.GetString() : null;
            var sessionKey = root.TryGetProperty("session_key", out var sessionKeyProp) ? sessionKeyProp.GetString() : null;

            _logger.LogInformation("[微信登录] 解析结果: openid={OpenId}, unionid={UnionId}, session_key={SessionKey}", 
                openId ?? "null", 
                unionId ?? "null", 
                string.IsNullOrEmpty(sessionKey) ? "null" : "已获取");

            if (string.IsNullOrEmpty(openId))
            {
                _logger.LogError("[微信登录] 微信API响应中缺少openid");
                return new WechatAuthResult
                {
                    Success = false,
                    ErrorMessage = "微信返回数据异常"
                };
            }

            _logger.LogInformation("[微信登录] 成功获取openid: {OpenId}", openId);

            return new WechatAuthResult
            {
                Success = true,
                OpenId = openId,
                UnionId = unionId
            };
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "[微信登录] HTTP请求异常: {Message}", ex.Message);
            return new WechatAuthResult
            {
                Success = false,
                ErrorMessage = "网络连接失败"
            };
        }
        catch (JsonException ex)
        {
            _logger.LogError(ex, "[微信登录] JSON解析异常: {Message}", ex.Message);
            return new WechatAuthResult
            {
                Success = false,
                ErrorMessage = "响应数据格式错误"
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[微信登录] 未知异常: {Message}", ex.Message);
            return new WechatAuthResult
            {
                Success = false,
                ErrorMessage = "系统错误"
            };
        }
    }

    /// <summary>
    /// 获取微信授权的手机号
    /// </summary>
    public async Task<WechatMobileResult> GetMobileAsync(string code)
    {
        if (string.IsNullOrWhiteSpace(code))
        {
            _logger.LogWarning("GetMobileAsync called with empty code");
            return new WechatMobileResult
            {
                Success = false,
                ErrorMessage = "授权code不能为空"
            };
        }

        try
        {
            // 1. 先获取 access_token
            var accessToken = await GetAccessTokenAsync();
            if (string.IsNullOrEmpty(accessToken))
            {
                _logger.LogError("Failed to get access_token for phone number API");
                return new WechatMobileResult
                {
                    Success = false,
                    ErrorMessage = "获取access_token失败"
                };
            }

            // 2. 使用 access_token 作为 URL 参数，code 放在请求体中
            var url = $"{WechatGetPhoneNumberUrl}?access_token={accessToken}";
            var requestBody = new { code = code };
            var jsonContent = new StringContent(
                JsonSerializer.Serialize(requestBody),
                System.Text.Encoding.UTF8,
                "application/json");
            
            _logger.LogInformation("Calling WeChat API to get phone number with access_token");
            
            var response = await _httpClient.PostAsync(url, jsonContent);
            var content = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError("WeChat API returned error status {StatusCode}: {Content}", response.StatusCode, content);
                return new WechatMobileResult
                {
                    Success = false,
                    ErrorMessage = "微信API调用失败"
                };
            }

            using var jsonDoc = JsonDocument.Parse(content);
            var root = jsonDoc.RootElement;

            // 检查是否有错误
            if (root.TryGetProperty("errcode", out var errCode) && errCode.GetInt32() != 0)
            {
                var errMsg = root.TryGetProperty("errmsg", out var msg) ? msg.GetString() : "未知错误";
                _logger.LogWarning("WeChat API returned error: {ErrorCode} - {ErrorMessage}", errCode.GetInt32(), errMsg);
                return new WechatMobileResult
                {
                    Success = false,
                    ErrorMessage = $"获取手机号失败: {errMsg}"
                };
            }

            // 提取手机号
            string? mobile = null;
            if (root.TryGetProperty("phone_info", out var phoneInfo))
            {
                mobile = phoneInfo.TryGetProperty("phoneNumber", out var phoneNumber) 
                    ? phoneNumber.GetString() 
                    : null;
            }

            if (string.IsNullOrEmpty(mobile))
            {
                _logger.LogError("WeChat API response missing phone number");
                return new WechatMobileResult
                {
                    Success = false,
                    ErrorMessage = "微信返回数据异常"
                };
            }

            _logger.LogInformation("Successfully retrieved phone number from WeChat API");

            return new WechatMobileResult
            {
                Success = true,
                Mobile = mobile
            };
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "HTTP request error when calling WeChat API");
            return new WechatMobileResult
            {
                Success = false,
                ErrorMessage = "网络连接失败"
            };
        }
        catch (JsonException ex)
        {
            _logger.LogError(ex, "JSON parsing error when processing WeChat API response");
            return new WechatMobileResult
            {
                Success = false,
                ErrorMessage = "响应数据格式错误"
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unexpected error when calling WeChat API");
            return new WechatMobileResult
            {
                Success = false,
                ErrorMessage = "系统错误"
            };
        }
    }

    /// <summary>
    /// 获取小程序接口调用凭证（access_token）
    /// </summary>
    /// <param name="appId">小程序AppId（可选，不传则使用数据库默认配置）</param>
    /// <returns>access_token，失败返回null</returns>
    public async Task<string?> GetAccessTokenAsync(string? appId = null)
    {
        try
        {
            // 从数据库获取配置
            var wechatConfig = await GetWechatSettingFromDbAsync();
            if (wechatConfig == null)
            {
                _logger.LogError("无法获取access_token：未找到小程序配置，请在后台管理系统中配置 miniprogram_setting");
                return null;
            }

            // 确定使用哪个AppId和AppSecret
            var targetAppId = appId ?? wechatConfig.AppId;
            var targetAppSecret = await GetAppSecretByAppIdAsync(targetAppId);

            if (string.IsNullOrEmpty(targetAppId) || string.IsNullOrEmpty(targetAppSecret))
            {
                _logger.LogError("无法获取access_token：AppId或AppSecret为空");
                return null;
            }

            // 尝试从Redis缓存获取
            var cacheKey = $"{AccessTokenCacheKeyPrefix}{targetAppId}";
            var cachedToken = await _redisService.GetStringAsync(cacheKey);
            if (!string.IsNullOrEmpty(cachedToken))
            {
                _logger.LogDebug("从缓存获取access_token: AppId={AppId}", targetAppId);
                return cachedToken;
            }

            // 调用微信API获取新的access_token
            var url = $"{WechatGetAccessTokenUrl}?grant_type=client_credential&appid={targetAppId}&secret={targetAppSecret}";
            
            _logger.LogInformation("调用微信API获取access_token: AppId={AppId}", targetAppId);
            
            var response = await _httpClient.GetAsync(url);
            var content = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError("微信API返回错误状态 {StatusCode}: {Content}", response.StatusCode, content);
                return null;
            }

            using var jsonDoc = JsonDocument.Parse(content);
            var root = jsonDoc.RootElement;

            // 检查是否有错误
            if (root.TryGetProperty("errcode", out var errCode) && errCode.GetInt32() != 0)
            {
                var errMsg = root.TryGetProperty("errmsg", out var msg) ? msg.GetString() : "未知错误";
                _logger.LogWarning("微信API返回错误: {ErrorCode} - {ErrorMessage}", errCode.GetInt32(), errMsg);
                return null;
            }

            // 提取access_token和过期时间
            var accessToken = root.TryGetProperty("access_token", out var tokenProp) ? tokenProp.GetString() : null;
            var expiresIn = root.TryGetProperty("expires_in", out var expiresProp) ? expiresProp.GetInt32() : 7200;

            if (string.IsNullOrEmpty(accessToken))
            {
                _logger.LogError("微信API响应中缺少access_token");
                return null;
            }

            // 缓存access_token（提前5分钟过期，避免边界问题）
            var cacheExpiry = TimeSpan.FromSeconds(Math.Max(expiresIn - 300, 60));
            await _redisService.SetStringAsync(cacheKey, accessToken, cacheExpiry);

            _logger.LogInformation("成功获取access_token: AppId={AppId}, ExpiresIn={ExpiresIn}s", targetAppId, expiresIn);

            return accessToken;
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "获取access_token时HTTP请求错误");
            return null;
        }
        catch (JsonException ex)
        {
            _logger.LogError(ex, "获取access_token时JSON解析错误");
            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取access_token时发生未知错误");
            return null;
        }
    }

    /// <summary>
    /// 获取小程序码（无限制）
    /// 调用微信API getwxacodeunlimit 生成小程序码
    /// </summary>
    /// <param name="scene">场景值，最大32个可见字符</param>
    /// <param name="page">小程序页面路径（可选）</param>
    /// <param name="width">二维码宽度，默认430</param>
    /// <returns>小程序码图片字节数组，失败返回null</returns>
    public async Task<byte[]?> GetWxaCodeUnlimitAsync(string scene, string? page = null, int width = 430)
    {
        try
        {
            _logger.LogInformation("[小程序码] 开始生成: scene={Scene}, page={Page}, width={Width}", scene, page, width);

            // 1. 获取 access_token
            var accessToken = await GetAccessTokenAsync();
            if (string.IsNullOrEmpty(accessToken))
            {
                _logger.LogError("[小程序码] 获取access_token失败");
                return null;
            }

            // 2. 构建请求参数
            var requestData = new Dictionary<string, object>
            {
                { "scene", scene },
                { "width", width },
                { "auto_color", false },
                { "line_color", new { r = 0, g = 0, b = 0 } },
                { "is_hyaline", false }
            };

            // 如果指定了页面路径，添加page参数
            if (!string.IsNullOrEmpty(page))
            {
                requestData["page"] = page;
            }

            // 3. 调用微信API
            var url = $"{WechatGetWxaCodeUnlimitUrl}?access_token={accessToken}";
            var jsonContent = new StringContent(
                JsonSerializer.Serialize(requestData),
                System.Text.Encoding.UTF8,
                "application/json");

            _logger.LogInformation("[小程序码] 调用微信API: {Url}", WechatGetWxaCodeUnlimitUrl);

            var response = await _httpClient.PostAsync(url, jsonContent);
            
            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError("[小程序码] 微信API返回HTTP错误: {StatusCode}", response.StatusCode);
                return null;
            }

            // 4. 检查响应内容类型
            var contentType = response.Content.Headers.ContentType?.MediaType;
            
            // 如果返回的是图片，直接返回字节数组
            if (contentType != null && contentType.StartsWith("image/"))
            {
                var imageBytes = await response.Content.ReadAsByteArrayAsync();
                _logger.LogInformation("[小程序码] 生成成功，图片大小: {Size} bytes", imageBytes.Length);
                return imageBytes;
            }

            // 如果返回的是JSON，说明有错误
            var content = await response.Content.ReadAsStringAsync();
            _logger.LogWarning("[小程序码] 微信API返回错误: {Content}", content);

            try
            {
                using var jsonDoc = JsonDocument.Parse(content);
                var root = jsonDoc.RootElement;
                
                if (root.TryGetProperty("errcode", out var errCode))
                {
                    var errMsg = root.TryGetProperty("errmsg", out var msg) ? msg.GetString() : "未知错误";
                    _logger.LogError("[小程序码] 微信API错误: errcode={ErrorCode}, errmsg={ErrorMessage}", 
                        errCode.GetInt32(), errMsg);
                }
            }
            catch
            {
                // JSON解析失败，忽略
            }

            return null;
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "[小程序码] HTTP请求错误");
            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[小程序码] 生成失败");
            return null;
        }
    }

    /// <summary>
    /// 根据AppId获取对应的AppSecret（异步版本，从数据库读取）
    /// </summary>
    private async Task<string> GetAppSecretByAppIdAsync(string appId)
    {
        // 从数据库获取配置
        var wechatConfig = await GetWechatSettingFromDbAsync();
        if (wechatConfig != null && wechatConfig.AppId == appId)
        {
            return wechatConfig.AppSecret;
        }

        // 从小程序配置列表中查找
        var miniprogram = _wechatPaySettings.Miniprograms.FirstOrDefault(m => m.AppId == appId);
        if (miniprogram != null)
        {
            return miniprogram.AppSecret;
        }

        // 如果都没找到，返回数据库默认配置的AppSecret
        _logger.LogWarning("未找到AppId {AppId} 的配置，使用数据库默认配置", appId);
        return wechatConfig?.AppSecret ?? string.Empty;
    }

    /// <summary>
    /// 创建支付订单（原生微信支付）
    /// </summary>
    public async Task<CreatePayResult> CreatePayOrderAsync(CreatePayRequest request)
    {
        try
        {
            _logger.LogInformation("[创建支付订单] 开始处理: UserId={UserId}, Price={Price}, Title={Title}, Attach={Attach}",
                request.UserId, request.Price, request.Title, request.Attach);

            // 如果金额为0，直接返回成功（免费订单）
            if (request.Price <= 0)
            {
                var freeOrderNo = GenerateOrderNo(request.Prefix, "MON", "YD", "MP0");
                _logger.LogInformation("[创建支付订单] 免费订单，直接返回成功: OrderNo={OrderNo}", freeOrderNo);
                return new CreatePayResult
                {
                    Status = 1,
                    OrderNo = freeOrderNo,
                    Res = null
                };
            }

            // 获取商户配置（优先从数据库读取）
            var merchantConfig = await GetMerchantConfigAsync();
            if (merchantConfig == null)
            {
                _logger.LogError("[创建支付订单] 未找到商户配置");
                return new CreatePayResult
                {
                    Status = 0,
                    Message = "支付配置错误",
                    OrderNo = string.Empty
                };
            }

            // 生成订单号：前缀 + 商户前缀 + 小程序前缀 + 支付类型 + 时间戳 + 随机数
            var orderNo = GenerateOrderNo(request.Prefix, merchantConfig.OrderPrefix, "YD", "MP0");

            // 截取标题（最多30个字符）
            var title = request.Title.Length > 30 ? request.Title.Substring(0, 30) : request.Title;

            // 生成随机字符串
            var nonceStr = GenerateNonceStr();
            var callbackNonceStr = GenerateNonceStr();

            // 生成回调通知URL
            var notifyUrl = GenerateNotifyUrl(request.Attach, request.UserId, orderNo, callbackNonceStr);

            // 获取客户端IP
            var clientIp = "127.0.0.1"; // 实际应从请求中获取

            // 构建统一下单参数
            var unifiedOrderParams = new SortedDictionary<string, string>
            {
                { "appid", merchantConfig.AppId },
                { "mch_id", merchantConfig.MchId },
                { "nonce_str", nonceStr },
                { "body", title },
                { "attach", request.Attach },
                { "out_trade_no", orderNo },
                { "notify_url", notifyUrl },
                { "total_fee", ((int)(request.Price * 100)).ToString() }, // 转换为分
                { "spbill_create_ip", clientIp },
                { "trade_type", "JSAPI" },
                { "openid", request.OpenId }
            };

            // 生成签名
            var sign = MakeSign(unifiedOrderParams, merchantConfig.Key);
            unifiedOrderParams.Add("sign", sign);

            // 转换为XML
            var xmlData = DictToXml(unifiedOrderParams);

            _logger.LogInformation("[创建支付订单] 调用微信统一下单API: OrderNo={OrderNo}", orderNo);

            // 调用微信统一下单API
            var content = new StringContent(xmlData, System.Text.Encoding.UTF8, "application/xml");
            var response = await _httpClient.PostAsync(_wechatPaySettings.UnifiedOrderUrl, content);
            var responseContent = await response.Content.ReadAsStringAsync();

            _logger.LogInformation("[创建支付订单] 微信统一下单响应: {Response}", responseContent);

            // 解析响应
            var result = XmlToDict(responseContent);

            if (result.TryGetValue("return_code", out var returnCode) && returnCode == "SUCCESS" &&
                result.TryGetValue("result_code", out var resultCode) && resultCode == "SUCCESS")
            {
                // 获取 prepay_id
                if (!result.TryGetValue("prepay_id", out var prepayId))
                {
                    _logger.LogError("[创建支付订单] 微信返回数据缺少 prepay_id");
                    return new CreatePayResult
                    {
                        Status = 0,
                        Message = "微信返回数据异常",
                        OrderNo = string.Empty
                    };
                }

                // 保存订单通知记录
                var orderNotify = new OrderNotify
                {
                    OrderNo = orderNo,
                    NotifyUrl = notifyUrl,
                    NonceStr = callbackNonceStr,
                    PayTime = DateTime.UtcNow,
                    PayAmount = request.Price,
                    Status = 0, // 待支付
                    RetryCount = 0,
                    Attach = request.Attach,
                    OpenId = request.OpenId,
                    Extend = JsonSerializer.Serialize(new { orderType = request.Attach, title = title }),
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                _dbContext.OrderNotifies.Add(orderNotify);
                await _dbContext.SaveChangesAsync();

                // 生成前端支付参数
                var timeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
                var payNonceStr = GenerateNonceStr();

                var payParams = new SortedDictionary<string, string>
                {
                    { "appId", merchantConfig.AppId },
                    { "timeStamp", timeStamp },
                    { "nonceStr", payNonceStr },
                    { "package", $"prepay_id={prepayId}" },
                    { "signType", "MD5" }
                };

                var paySign = MakeSign(payParams, merchantConfig.Key);

                _logger.LogInformation("[创建支付订单] 订单创建成功: OrderNo={OrderNo}, PrepayId={PrepayId}", orderNo, prepayId);

                return new CreatePayResult
                {
                    Status = 1,
                    OrderNo = orderNo,
                    Res = new NativePayParams
                    {
                        AppId = merchantConfig.AppId,
                        TimeStamp = timeStamp,
                        NonceStr = payNonceStr,
                        Package = $"prepay_id={prepayId}",
                        SignType = "MD5",
                        PaySign = paySign
                    }
                };
            }
            else
            {
                // 解析错误信息
                var errorMsg = "微信支付接口返回异常";
                if (result.TryGetValue("return_msg", out var returnMsg))
                {
                    errorMsg = returnMsg;
                }
                else if (result.TryGetValue("err_code_des", out var errCodeDes))
                {
                    errorMsg = errCodeDes;
                }

                _logger.LogError("[创建支付订单] 微信统一下单失败: {Error}, Response: {Response}", errorMsg, responseContent);

                return new CreatePayResult
                {
                    Status = 0,
                    Message = errorMsg,
                    OrderNo = string.Empty
                };
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[创建支付订单] 创建失败: UserId={UserId}", request.UserId);
            return new CreatePayResult
            {
                Status = 0,
                Message = "创建支付订单失败",
                OrderNo = string.Empty
            };
        }
    }

    /// <summary>
    /// 从数据库获取微信小程序配置
    /// 仅从 miniprogram_setting 读取，无配置则返回 null
    /// </summary>
    private async Task<WechatSettings?> GetWechatSettingFromDbAsync()
    {
        try
        {
            // 从 miniprogram_setting 读取小程序配置
            var miniprogramConfig = await _dbContext.Configs
                .Where(c => c.ConfigKey == "miniprogram_setting")
                .Select(c => c.ConfigValue)
                .FirstOrDefaultAsync();

            if (string.IsNullOrEmpty(miniprogramConfig))
            {
                _logger.LogWarning("[微信配置] 数据库中未找到 miniprogram_setting 配置");
                return null;
            }

            var config = JsonSerializer.Deserialize<JsonElement>(miniprogramConfig);
            
            if (!config.TryGetProperty("miniprograms", out var miniprograms) || miniprograms.ValueKind != JsonValueKind.Array)
            {
                _logger.LogWarning("[微信配置] miniprogram_setting 配置格式错误，缺少 miniprograms 数组");
                return null;
            }

            // 查找默认小程序配置 (is_default = 1)
            foreach (var mp in miniprograms.EnumerateArray())
            {
                var isDefault = mp.TryGetProperty("is_default", out var isDefaultProp) && 
                    (isDefaultProp.ValueKind == JsonValueKind.Number ? isDefaultProp.GetInt32() == 1 : isDefaultProp.GetString() == "1");
                
                if (isDefault)
                {
                    var appId = mp.TryGetProperty("appid", out var appIdProp) ? appIdProp.GetString() : null;
                    var appSecret = mp.TryGetProperty("appsecret", out var appSecretProp) ? appSecretProp.GetString() : null;

                    if (!string.IsNullOrEmpty(appId) && !string.IsNullOrEmpty(appSecret))
                    {
                        _logger.LogDebug("[微信配置] 从 miniprogram_setting 读取默认小程序配置: AppId={AppId}", 
                            appId.Length > 8 ? $"{appId.Substring(0, 4)}****{appId.Substring(appId.Length - 4)}" : appId);
                        return new WechatSettings
                        {
                            AppId = appId,
                            AppSecret = appSecret
                        };
                    }
                }
            }
            
            // 如果没有默认配置，使用第一个小程序配置
            var firstMp = miniprograms.EnumerateArray().FirstOrDefault();
            if (firstMp.ValueKind == JsonValueKind.Object)
            {
                var appId = firstMp.TryGetProperty("appid", out var appIdProp) ? appIdProp.GetString() : null;
                var appSecret = firstMp.TryGetProperty("appsecret", out var appSecretProp) ? appSecretProp.GetString() : null;

                if (!string.IsNullOrEmpty(appId) && !string.IsNullOrEmpty(appSecret))
                {
                    _logger.LogDebug("[微信配置] 从 miniprogram_setting 读取第一个小程序配置: AppId={AppId}", 
                        appId.Length > 8 ? $"{appId.Substring(0, 4)}****{appId.Substring(appId.Length - 4)}" : appId);
                    return new WechatSettings
                    {
                        AppId = appId,
                        AppSecret = appSecret
                    };
                }
            }

            _logger.LogWarning("[微信配置] miniprogram_setting 中未找到有效的小程序配置");
            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[微信配置] 从数据库读取配置失败");
            return null;
        }
    }

    /// <summary>
    /// 获取商户配置（从数据库读取）
    /// </summary>
    private async Task<WechatPayMerchantConfig?> GetMerchantConfigAsync()
    {
        try
        {
            // 从数据库读取 weixinpay 配置
            var weixinpayConfig = await _dbContext.Configs
                .Where(c => c.ConfigKey == "weixinpay")
                .Select(c => c.ConfigValue)
                .FirstOrDefaultAsync();

            if (string.IsNullOrEmpty(weixinpayConfig))
            {
                _logger.LogError("[微信支付] 数据库中未找到 weixinpay 配置");
                return null;
            }

            var config = JsonSerializer.Deserialize<JsonElement>(weixinpayConfig);
            
            var mchId = config.TryGetProperty("mch_id", out var mchIdProp) ? mchIdProp.GetString() : null;
            var appId = config.TryGetProperty("appid", out var appIdProp) ? appIdProp.GetString() : null;
            var key = config.TryGetProperty("keys", out var keysProp) ? keysProp.GetString() : null;

            if (string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(key))
            {
                _logger.LogError("[微信支付] weixinpay 配置不完整，缺少 mch_id 或 keys");
                return null;
            }

            // 如果 weixinpay 中没有 appid，从 miniprogram_setting 获取
            if (string.IsNullOrEmpty(appId))
            {
                var wechatConfig = await GetWechatSettingFromDbAsync();
                appId = wechatConfig?.AppId;
            }

            if (string.IsNullOrEmpty(appId))
            {
                _logger.LogError("[微信支付] 未找到有效的 AppId 配置");
                return null;
            }

            _logger.LogInformation("[微信支付] 从数据库读取配置: MchId={MchId}, AppId={AppId}", mchId, appId);
            return new WechatPayMerchantConfig
            {
                Name = "数据库配置",
                MchId = mchId,
                AppId = appId,
                Key = key,
                OrderPrefix = "MYH",
                Weight = 1
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[微信支付] 从数据库读取配置失败");
            return null;
        }
    }

    /// <summary>
    /// 生成随机字符串
    /// </summary>
    private static string GenerateNonceStr(int length = 32)
    {
        const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var random = new Random();
        return new string(Enumerable.Repeat(chars, length)
            .Select(s => s[random.Next(s.Length)]).ToArray());
    }

    /// <summary>
    /// 生成回调通知URL
    /// </summary>
    private string GenerateNotifyUrl(string orderType, int userId, string orderNo, string nonceStr)
    {
        var baseUrl = _wechatPaySettings.NotifyBaseUrl.TrimEnd('/');
        return $"{baseUrl}/api/pay/notify?payment_type=wxpay&order_type={orderType}&user_id={userId}&order_no={orderNo}&nonce_str={nonceStr}";
    }

    /// <summary>
    /// 生成签名（MD5）
    /// </summary>
    private static string MakeSign(SortedDictionary<string, string> parameters, string key)
    {
        var sb = new System.Text.StringBuilder();
        foreach (var kvp in parameters)
        {
            if (!string.IsNullOrEmpty(kvp.Value) && kvp.Key != "sign")
            {
                sb.Append($"{kvp.Key}={kvp.Value}&");
            }
        }
        sb.Append($"key={key}");

        using var md5 = System.Security.Cryptography.MD5.Create();
        var inputBytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
        var hashBytes = md5.ComputeHash(inputBytes);
        return BitConverter.ToString(hashBytes).Replace("-", "").ToUpper();
    }

    /// <summary>
    /// 字典转XML
    /// </summary>
    private static string DictToXml(SortedDictionary<string, string> dict)
    {
        var sb = new System.Text.StringBuilder();
        sb.Append("<xml>");
        foreach (var kvp in dict)
        {
            sb.Append($"<{kvp.Key}><![CDATA[{kvp.Value}]]></{kvp.Key}>");
        }
        sb.Append("</xml>");
        return sb.ToString();
    }

    /// <summary>
    /// XML转字典
    /// </summary>
    private static Dictionary<string, string> XmlToDict(string xml)
    {
        var dict = new Dictionary<string, string>();
        try
        {
            var doc = System.Xml.Linq.XDocument.Parse(xml);
            if (doc.Root != null)
            {
                foreach (var element in doc.Root.Elements())
                {
                    dict[element.Name.LocalName] = element.Value;
                }
            }
        }
        catch
        {
            // 解析失败返回空字典
        }
        return dict;
    }

    /// <summary>
    /// 生成订单号
    /// 格式：前缀(3位) + 商户前缀(3位) + 项目前缀(2位) + 支付类型(3位) + 时间戳 + 随机数
    /// </summary>
    private string GenerateOrderNo(string prefix, string merchantPrefix, string projectPrefix, string payType)
    {
        var timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
        var random = new Random().Next(1000, 9999);
        return $"{prefix}{merchantPrefix}{projectPrefix}{payType}{timestamp}{random}";
    }

    /// <summary>
    /// 上传微信小程序发货信息
    /// 调用微信API upload_shipping_info 将订单标记为已发货
    /// </summary>
    public async Task<WechatShippingResult> UploadShippingInfoAsync(WechatShippingRequest request)
    {
        const string uploadShippingUrl = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info";

        try
        {
            // 1. 参数验证
            if (string.IsNullOrEmpty(request.OpenId))
            {
                return new WechatShippingResult
                {
                    Success = false,
                    ErrorCode = -1,
                    ErrorMessage = "OpenId不能为空"
                };
            }

            if (string.IsNullOrEmpty(request.OrderNo))
            {
                return new WechatShippingResult
                {
                    Success = false,
                    ErrorCode = -1,
                    ErrorMessage = "订单号不能为空"
                };
            }

            // 2. 获取商户配置（根据订单号匹配）
            var merchantConfig = await GetMerchantConfigByOrderNoAsync(request.OrderNo);
            if (merchantConfig == null)
            {
                _logger.LogWarning("发货失败：未找到订单对应的商户配置, OrderNo={OrderNo}", request.OrderNo);
                return new WechatShippingResult
                {
                    Success = false,
                    ErrorCode = -1,
                    ErrorMessage = "未找到商户配置",
                    NeedRetry = true
                };
            }

            var mchId = request.MchId ?? merchantConfig.MchId;
            var appId = request.AppId ?? merchantConfig.AppId;

            // 3. 获取access_token
            var accessToken = await GetAccessTokenAsync(appId);
            if (string.IsNullOrEmpty(accessToken))
            {
                _logger.LogWarning("发货失败：获取access_token失败, OrderNo={OrderNo}", request.OrderNo);
                return new WechatShippingResult
                {
                    Success = false,
                    ErrorCode = -1,
                    ErrorMessage = "获取access_token失败",
                    NeedRetry = true
                };
            }

            // 4. 构建请求参数 - 直接构建 JSON 字符串，与 PHP 保持一致
            var itemDesc = request.ItemDesc ?? GetDefaultItemDesc(request.OrderNo);
            var uploadTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss") + "+08:00";

            // 使用字符串模板构建 JSON，确保格式与微信要求一致
            var jsonContent = $$"""
                {
                    "order_key": {
                        "order_number_type": 1,
                        "mchid": "{{mchId}}",
                        "out_trade_no": "{{request.OrderNo}}"
                    },
                    "logistics_type": {{request.LogisticsType}},
                    "delivery_mode": 1,
                    "shipping_list": [
                        {
                            "item_desc": "{{itemDesc}}"
                        }
                    ],
                    "upload_time": "{{uploadTime}}",
                    "payer": {
                        "openid": "{{request.OpenId}}"
                    }
                }
                """;

            _logger.LogInformation("调用微信发货接口: OrderNo={OrderNo}, MchId={MchId}, OpenId={OpenId}",
                request.OrderNo, mchId, request.OpenId);
            _logger.LogDebug("发货请求内容: {JsonContent}", jsonContent);

            // 5. 发送请求
            var url = $"{uploadShippingUrl}?access_token={accessToken}";
            var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
            var response = await _httpClient.PostAsync(url, content);
            var responseContent = await response.Content.ReadAsStringAsync();

            _logger.LogDebug("微信发货接口响应: {Response}", responseContent);

            // 6. 解析响应
            using var jsonDoc = JsonDocument.Parse(responseContent);
            var root = jsonDoc.RootElement;

            var errCode = root.TryGetProperty("errcode", out var errCodeProp) ? errCodeProp.GetInt32() : -1;
            var errMsg = root.TryGetProperty("errmsg", out var errMsgProp) ? errMsgProp.GetString() : "未知错误";

            if (errCode == 0)
            {
                _logger.LogInformation("微信发货成功: OrderNo={OrderNo}", request.OrderNo);
                return new WechatShippingResult
                {
                    Success = true,
                    ErrorCode = 0,
                    ErrorMessage = "ok"
                };
            }
            else
            {
                _logger.LogWarning("微信发货失败: OrderNo={OrderNo}, ErrCode={ErrCode}, ErrMsg={ErrMsg}",
                    request.OrderNo, errCode, errMsg);
                return new WechatShippingResult
                {
                    Success = false,
                    ErrorCode = errCode,
                    ErrorMessage = errMsg,
                    NeedRetry = ShouldRetry(errCode)
                };
            }
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "微信发货HTTP请求异常: OrderNo={OrderNo}", request.OrderNo);
            return new WechatShippingResult
            {
                Success = false,
                ErrorCode = -1,
                ErrorMessage = $"HTTP请求异常: {ex.Message}",
                NeedRetry = true
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "微信发货异常: OrderNo={OrderNo}", request.OrderNo);
            return new WechatShippingResult
            {
                Success = false,
                ErrorCode = -1,
                ErrorMessage = $"发货异常: {ex.Message}",
                NeedRetry = true
            };
        }
    }

    /// <summary>
    /// 根据订单号获取商户配置
    /// </summary>
    private async Task<WechatPayMerchantConfig?> GetMerchantConfigByOrderNoAsync(string orderNo)
    {
        // 优先使用 WechatPayConfigService（支持多商户配置）
        if (_wechatPayConfigService != null)
        {
            var config = _wechatPayConfigService.GetMerchantByOrderNo(orderNo);
            if (!string.IsNullOrEmpty(config.MchId))
            {
                _logger.LogInformation("[发货] 使用 WechatPayConfigService 获取商户配置: MchId={MchId}, AppId={AppId}", 
                    config.MchId, config.AppId);
                return config;
            }
        }

        // 回退到旧的配置读取方式
        return await GetMerchantConfigAsync();
    }

    /// <summary>
    /// 获取默认商品描述
    /// </summary>
    private static string GetDefaultItemDesc(string orderNo)
    {
        // 发货订单（FH_开头）使用不同的描述
        if (orderNo.StartsWith("FH_", StringComparison.OrdinalIgnoreCase))
        {
            return "本单购买的商品正在打包，请联系客服获取物流信息";
        }
        return "本单购买商品已发放至[小程序盒柜]";
    }

    /// <summary>
    /// 判断是否需要重试
    /// </summary>
    private static bool ShouldRetry(int errCode)
    {
        // 发货失败都应该重试，不管什么错误码
        // 常见错误码：
        // 40001/42001: access_token无效或过期
        // -1: 系统繁忙
        // 10060001: 支付单不存在（微信系统同步延迟）
        // 10060003: 支付单状态异常
        return true;
    }
}
