using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models;
using HoneyBox.Model.Models.Goods;
using HoneyBox.Model.Models.Lottery;
using HoneyBox.Model.Models.Order;
using HoneyBox.Model.Models.Payment;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Core.Services;

/// <summary>
/// 订单服务实现
/// </summary>
public class OrderService : IOrderService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly ILogger<OrderService> _logger;
    private readonly ILotteryEngine _lotteryEngine;
    private readonly IWechatPayService _wechatPayService;

    // 抽奖赏品ID范围 [10, 33]
    private static readonly int[] ShangPrizeIdRange = { 10, 33 };
    // 统计次数赏品ID范围 [10, 38]
    private static readonly int[] ShangCountIdRange = { 10, 38 };
    // 无限赏赏品ID范围 [34, 38]
    private static readonly int[] InfiniteShangPrizeIdRange = { 34, 38 };
    // 无限赏商品类型
    private static readonly int[] InfiniteGoodsTypes = { 2, 8, 9, 10, 16, 17 };

    public OrderService(
        HoneyBoxDbContext dbContext, 
        ILogger<OrderService> logger, 
        ILotteryEngine lotteryEngine,
        IWechatPayService wechatPayService)
    {
        _dbContext = dbContext;
        _logger = logger;
        _lotteryEngine = lotteryEngine;
        _wechatPayService = wechatPayService;
    }

    #region 订单金额计算

    /// <inheritdoc />
    public async Task<OrderCalculationDto> CalculateOrderMoneyAsync(int userId, OrderMoneyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.Money, u.Integral, u.Money2, u.IsTest })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 2. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .Select(g => new
            {
                g.Id,
                g.Title,
                g.ImgUrlDetail,
                g.Type,
                g.Price,
                g.Status,
                g.IsShouZhe,
                g.QuanjuXiangou,
                g.DailyXiangou,
                g.ChoujiangXianzhi,
                g.LockIs,
                g.FlwStartTime,
                g.FlwEndTime
            })
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 3. 验证抽奖限制
        await ValidateDrawRestrictionsAsync(userId, goods.Id, goods.Type, goods.ChoujiangXianzhi,
            goods.QuanjuXiangou, goods.DailyXiangou, goods.FlwStartTime, goods.FlwEndTime, request.PrizeNum, user.IsTest);

        // 4. 获取商品扩展配置
        var goodsExtend = await GetGoodsExtendAsync(request.GoodsId, goods.Type);

        // 5. 计算订单金额
        var result = await CalculateOrderAmountAsync(
            userId,
            user.Money,
            user.Integral,
            user.Money2 ?? 0,
            user.IsTest,
            goods.Id,
            goods.Type,
            goods.Price,
            goods.IsShouZhe,
            request.PrizeNum,
            request.UseMoneyIs,
            request.UseIntegralIs,
            request.UseMoney2Is,
            ParseCouponId(request.CouponId),
            goodsExtend
        );

        // 6. 构建响应（兼容 PHP 旧版字段名）
        return new OrderCalculationDto
        {
            OrderTotal = result.OrderTotal.ToString("0.00"),
            OrderZheTotal = result.OrderZheTotal.ToString("0.00"),
            Price = result.Price.ToString("0.00"),
            Zhe = result.Zhe.ToString("0.00"),
            // 用户余额信息（兼容旧版字段名）
            Money = user.Money.ToString("0.00"),
            Integral = user.Integral.ToString("0.00"),
            Score = user.Money2 ?? 0,
            // 使用金额信息
            UseMoney = result.UseMoney.ToString("0.00"),
            UseIntegral = result.UseIntegral.ToString("0.00"),
            UseIntegralMoney = (result.UseIntegral / 100).ToString("0.00"),
            UseScore = result.UseMoney2,
            UseMoney2 = result.UseMoney2,
            // 优惠券信息
            CouponId = result.CouponId,
            CouponPrice = result.CouponPrice.ToString("0.00"),
            IsShouZhe = result.IsShouZhe ? 1 : 0,
            // 商品信息（兼容旧版字段名 goods）
            Goods = new GoodsInfoDto
            {
                Id = goods.Id,
                Title = goods.Title,
                ImgUrlDetail = FormatImageUrl(goods.ImgUrlDetail),
                Price = goods.Price.ToString("0.##"),
                Type = goods.Type,
                IsShouZhe = goods.IsShouZhe,
                QuanjuXiangou = goods.QuanjuXiangou,
                DailyXiangou = goods.DailyXiangou,
                PrizeNum = request.PrizeNum,
                ShouZhePrice = result.ShouZhePrice.ToString("0.00")
            },
            GoodsExtend = goodsExtend
        };
    }

    /// <summary>
    /// 解析优惠券ID
    /// </summary>
    private static int ParseCouponId(string? couponId)
    {
        if (string.IsNullOrEmpty(couponId))
            return 0;
        return int.TryParse(couponId, out var id) ? id : 0;
    }

    /// <summary>
    /// 验证抽奖限制
    /// </summary>
    private async Task ValidateDrawRestrictionsAsync(
        int userId, int goodsId, int goodsType, int choujiangXianzhi,
        int quanjuXiangou, int dailyXiangou,
        DateTime? flwStartTime, DateTime? flwEndTime,
        int prizeNum, int isTest)
    {
        // 1. 验证抽奖门槛
        if (choujiangXianzhi > 0 || goodsType == 15)
        {
            if (goodsType == 15)
            {
                // 福利屋活动验证
                if (flwStartTime.HasValue && flwEndTime.HasValue)
                {
                    var consumptionData = await GetUserConsumptionByTimeRangeAsync(userId, flwStartTime.Value, flwEndTime.Value);
                    if (consumptionData < choujiangXianzhi)
                    {
                        var remaining = Math.Round(choujiangXianzhi - consumptionData, 2);
                        throw new InvalidOperationException(
                            $"需在指定时间{flwStartTime.Value:yyyy-MM-dd HH:mm:ss}-{flwEndTime.Value:yyyy-MM-dd HH:mm:ss}消耗达到{choujiangXianzhi}钻石，即可加入房间，还需{remaining}钻石.");
                    }
                }
            }
            else
            {
                // 常规消费验证
                var userPrice = await _dbContext.Orders
                    .Where(o => o.Status == 1 && o.UserId == userId)
                    .SumAsync(o => o.Price);
                var userUseMoney = await _dbContext.Orders
                    .Where(o => o.Status == 1 && o.UserId == userId)
                    .SumAsync(o => o.UseMoney);

                var totalSpent = userPrice + userUseMoney;

                // 推广账号使用折扣后金额
                if (isTest > 0)
                {
                    totalSpent = await _dbContext.Orders
                        .Where(o => o.Status == 1 && o.UserId == userId)
                        .SumAsync(o => o.OrderZheTotal);
                }

                if (totalSpent < choujiangXianzhi)
                {
                    throw new InvalidOperationException($"消费满{choujiangXianzhi}元可参与 已消费{Math.Round(totalSpent, 2)}元");
                }
            }
        }

        // 2. 验证全局限购
        if (quanjuXiangou > 0)
        {
            var userQuanjuCount = await _dbContext.OrderItems
                .Where(oi => oi.GoodsId == goodsId
                    && oi.UserId == userId
                    && oi.ParentGoodsListId == 0)
                .CountAsync();

            if (userQuanjuCount >= quanjuXiangou)
            {
                throw new InvalidOperationException($"当前限购{quanjuXiangou}次");
            }

            var nowPrizeNum = prizeNum + userQuanjuCount;
            if (nowPrizeNum > quanjuXiangou)
            {
                throw new InvalidOperationException($"购买超出限制,还允许购买{quanjuXiangou - userQuanjuCount}次");
            }
        }

        // 3. 验证每日限购
        if (dailyXiangou > 0)
        {
            var todayStart = DateTime.Today;
            var todayStartTimestamp = new DateTimeOffset(todayStart).ToUnixTimeSeconds();

            var userTodayCount = await _dbContext.OrderItems
                .Where(oi => oi.GoodsId == goodsId
                    && oi.UserId == userId
                    && oi.Addtime >= todayStartTimestamp)
                .CountAsync();

            if (userTodayCount >= dailyXiangou)
            {
                throw new InvalidOperationException($"今日限购{dailyXiangou}次");
            }

            var nowPrizeNum = prizeNum + userTodayCount;
            if (nowPrizeNum > dailyXiangou)
            {
                throw new InvalidOperationException($"购买超出限制,今日还允许购买{dailyXiangou - userTodayCount}次");
            }
        }
    }

    /// <summary>
    /// 获取用户在指定时间范围内的消费金额
    /// </summary>
    private async Task<decimal> GetUserConsumptionByTimeRangeAsync(int userId, DateTime startTime, DateTime endTime)
    {
        var startTimestamp = new DateTimeOffset(startTime).ToUnixTimeSeconds();
        var endTimestamp = new DateTimeOffset(endTime).ToUnixTimeSeconds();

        return await _dbContext.Orders
            .Where(o => o.Status == 1
                && o.UserId == userId
                && o.Addtime >= startTimestamp
                && o.Addtime <= endTimestamp)
            .SumAsync(o => o.UseMoney);
    }

    /// <summary>
    /// 获取商品扩展配置
    /// </summary>
    private async Task<GoodsExtendDto> GetGoodsExtendAsync(int goodsId, int goodsType)
    {
        // 先从goods_extensions表获取
        var goodsExtend = await _dbContext.GoodsExtensions
            .Where(ge => ge.GoodsId == goodsId)
            .Select(ge => new GoodsExtendDto
            {
                PayWechat = ge.PayWechat,
                PayBalance = ge.PayBalance,
                PayCurrency = ge.PayCurrency,
                PayCurrency2 = ge.PayCurrency2,
                PayCoupon = ge.PayCoupon,
                IsDeduction = ge.IsDeduction
            })
            .FirstOrDefaultAsync();

        if (goodsExtend != null)
        {
            return goodsExtend;
        }

        // 如果没有，从goods_types表获取默认配置
        var goodsTypeConfig = await _dbContext.GoodsTypes
            .Where(gt => gt.Value == goodsType)
            .Select(gt => new GoodsExtendDto
            {
                PayWechat = gt.PayWechat,
                PayBalance = gt.PayBalance,
                PayCurrency = gt.PayCurrency,
                PayCurrency2 = gt.PayCurrency2,
                PayCoupon = gt.PayCoupon,
                IsDeduction = gt.IsDeduction
            })
            .FirstOrDefaultAsync();

        return goodsTypeConfig ?? new GoodsExtendDto
        {
            PayWechat = 1,
            PayBalance = 0,
            PayCurrency = 0,
            PayCurrency2 = 0,
            PayCoupon = 0,
            IsDeduction = 0
        };
    }

    /// <summary>
    /// 计算订单金额
    /// </summary>
    private async Task<OrderCalculationResult> CalculateOrderAmountAsync(
        int userId,
        decimal userMoney,
        decimal userIntegral,
        decimal userMoney2,
        int isTest,
        int goodsId,
        int goodsType,
        decimal boxPrice,
        int isShouZhe,
        int prizeNum,
        int useMoneyIs,
        int useIntegralIs,
        int useMoney2Is,
        int couponId,
        GoodsExtendDto goodsExtend)
    {
        var result = new OrderCalculationResult();

        // 1. 首抽五折处理
        decimal shouZhePrice = 0;
        if (goodsType != 5 && goodsType != 10 && goodsType != 15)
        {
            // 检查用户是否有已支付订单
            var hasPaidOrder = await _dbContext.Orders
                .AnyAsync(o => o.UserId == userId && o.Status == 1);

            if (!hasPaidOrder && isShouZhe == 1)
            {
                shouZhePrice = Math.Round(boxPrice * 0.5m, 2);
                result.IsShouZhe = true;
                result.ShouZhePrice = shouZhePrice;
            }
        }

        // 2. 计算总价
        decimal price = boxPrice * prizeNum - shouZhePrice;
        result.OrderTotal = price;
        result.OrderZheTotal = price;

        // 3. 优惠券处理 (首抽五折时不能使用优惠券)
        if (shouZhePrice <= 0 && couponId > 0 && goodsExtend.PayCoupon == 1)
        {
            // 检查每日优惠券使用次数限制
            var dailyCouponLimit = await GetDailyCouponLimitAsync();
            var isDailyCouponValid = true;

            if (dailyCouponLimit > 0)
            {
                var todayStart = DateTime.Today;
                var todayEnd = todayStart.AddDays(1);

                var todayCount = await _dbContext.CouponReceives
                    .Where(cr => cr.UserId == userId
                        && cr.CreatedAt >= todayStart
                        && cr.CreatedAt < todayEnd
                        && cr.Status == 1)
                    .CountAsync();

                if (todayCount >= dailyCouponLimit)
                {
                    isDailyCouponValid = false;
                }
            }

            if (isDailyCouponValid)
            {
                // 获取优惠券信息
                var coupon = await _dbContext.CouponReceives
                    .Where(cr => cr.Id == couponId
                        && cr.Status == 0
                        && cr.UserId == userId
                        && cr.ManPrice <= price
                        && cr.EndTime > DateTime.Now)
                    .Select(cr => new { cr.Id, cr.Price })
                    .FirstOrDefaultAsync();

                if (coupon != null)
                {
                    result.CouponId = coupon.Id;
                    result.CouponPrice = coupon.Price ?? 0;
                }
            }
        }

        // 应用优惠券抵扣
        price -= result.CouponPrice;
        if (price < 0) price = 0;
        result.OrderZheTotal = price;

        // 4. 如果不是首抽五折，处理各种支付抵扣
        if (shouZhePrice <= 0)
        {
            var isZhifu = 0;

            // 4.1 余额抵扣
            if (useMoneyIs == 1 && goodsExtend.PayBalance == 1)
            {
                if (goodsExtend.IsDeduction == 1)
                {
                    // 抵扣模式
                    if (userMoney >= price)
                    {
                        result.UseMoney = price;
                        price = 0;
                    }
                    else
                    {
                        result.UseMoney = userMoney;
                        price -= userMoney;
                    }
                }
                else
                {
                    // 支付模式
                    if (userMoney >= price)
                    {
                        result.UseMoney = price;
                        price = 0;
                        isZhifu++;
                    }
                    else
                    {
                        // 支付模式下余额不足无法抵扣
                        throw new InvalidOperationException("钻石不足");
                    }
                }
            }

            // 4.2 货币1/积分抵扣 (1:100比例)
            if (useIntegralIs == 1 && goodsExtend.PayCurrency == 1)
            {
                var priceInCurrency = price * 100;
                if (goodsExtend.IsDeduction == 1)
                {
                    // 抵扣模式
                    if (userIntegral >= priceInCurrency)
                    {
                        result.UseIntegral = priceInCurrency;
                        price = 0;
                    }
                    else
                    {
                        result.UseIntegral = userIntegral;
                        price -= userIntegral / 100;
                    }
                }
                else
                {
                    // 支付模式
                    if (userIntegral >= priceInCurrency)
                    {
                        result.UseIntegral = priceInCurrency;
                        price = 0;
                        isZhifu++;
                    }
                    else
                    {
                        throw new InvalidOperationException("UU币不足");
                    }
                }
            }

            // 4.3 货币2/哈尼券抵扣 (1:100比例)
            if (useMoney2Is == 1 && goodsExtend.PayCurrency2 == 1)
            {
                var priceInCurrency2 = price * 100;
                if (goodsExtend.IsDeduction == 1)
                {
                    // 抵扣模式
                    if (userMoney2 >= priceInCurrency2)
                    {
                        result.UseMoney2 = priceInCurrency2;
                        price = 0;
                    }
                    else
                    {
                        result.UseMoney2 = userMoney2;
                        price -= userMoney2 / 100;
                    }
                }
                else
                {
                    // 支付模式
                    if (userMoney2 >= priceInCurrency2)
                    {
                        result.UseMoney2 = priceInCurrency2;
                        price = 0;
                        isZhifu++;
                    }
                    else
                    {
                        throw new InvalidOperationException("达达卷不足");
                    }
                }
            }

            // 如果是支付模式但未选择任何支付方式
            if (goodsExtend.IsDeduction == 0 && isZhifu == 0 && goodsExtend.PayWechat == 0)
            {
                throw new InvalidOperationException("请选择支付方式");
            }
        }

        result.Price = Math.Round(price, 2);
        return result;
    }

    /// <summary>
    /// 获取每日优惠券使用次数限制
    /// </summary>
    private async Task<int> GetDailyCouponLimitAsync()
    {
        var config = await _dbContext.Configs
            .Where(c => c.ConfigKey == "app_setting")
            .Select(c => c.ConfigValue)
            .FirstOrDefaultAsync();

        if (string.IsNullOrEmpty(config))
        {
            return 0;
        }

        try
        {
            var configObj = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(config);
            if (configObj != null && configObj.TryGetValue("daily_coupon_limit", out var limitObj))
            {
                if (int.TryParse(limitObj?.ToString(), out var limit))
                {
                    return limit;
                }
            }
        }
        catch
        {
            // 解析失败返回0
        }

        return 0;
    }

    /// <summary>
    /// 获取商城每日购买次数限制
    /// </summary>
    private async Task<int> GetExchangeTimesLimitAsync()
    {
        var config = await _dbContext.Configs
            .Where(c => c.ConfigKey == "app_setting")
            .Select(c => c.ConfigValue)
            .FirstOrDefaultAsync();

        if (string.IsNullOrEmpty(config))
        {
            return 0;
        }

        try
        {
            var configObj = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(config);
            if (configObj != null && configObj.TryGetValue("exchange_times", out var limitObj))
            {
                if (int.TryParse(limitObj?.ToString(), out var limit))
                {
                    return limit;
                }
            }
        }
        catch
        {
            // 解析失败返回0
        }

        return 0;
    }

    /// <summary>
    /// 格式化图片URL
    /// </summary>
    private static string FormatImageUrl(string? imgUrl)
    {
        if (string.IsNullOrEmpty(imgUrl))
        {
            return string.Empty;
        }

        // 如果已经是完整URL，直接返回
        if (imgUrl.StartsWith("http://") || imgUrl.StartsWith("https://"))
        {
            return imgUrl;
        }

        return imgUrl;
    }

    /// <summary>
    /// 订单金额计算结果
    /// </summary>
    private class OrderCalculationResult
    {
        public decimal OrderTotal { get; set; }
        public decimal OrderZheTotal { get; set; }
        public decimal Price { get; set; }
        public decimal Zhe { get; set; }
        public decimal UseMoney { get; set; }
        public decimal UseIntegral { get; set; }
        public decimal UseMoney2 { get; set; }
        public int CouponId { get; set; }
        public decimal CouponPrice { get; set; }
        public bool IsShouZhe { get; set; }
        public decimal ShouZhePrice { get; set; }
    }

    /// <inheritdoc />
    public async Task<OrderCalculationDto> CalculateInfiniteOrderMoneyAsync(int userId, InfiniteOrderMoneyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.Money, u.Integral, u.Money2, u.IsTest })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 2. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .Select(g => new
            {
                g.Id,
                g.Title,
                g.ImgUrlDetail,
                g.Type,
                g.Price,
                g.Status,
                g.IsShouZhe,
                g.QuanjuXiangou,
                g.DailyXiangou,
                g.ChoujiangXianzhi,
                g.LockIs,
                g.FlwStartTime,
                g.FlwEndTime
            })
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 3. 验证商品类型是否为无限赏类型
        if (!InfiniteGoodsTypes.Contains(goods.Type))
        {
            throw new InvalidOperationException("非法请求");
        }

        // 4. 验证抽奖限制
        await ValidateDrawRestrictionsAsync(userId, goods.Id, goods.Type, goods.ChoujiangXianzhi,
            goods.QuanjuXiangou, goods.DailyXiangou, goods.FlwStartTime, goods.FlwEndTime, request.PrizeNum, user.IsTest);

        // 5. 获取商品扩展配置
        var goodsExtend = await GetGoodsExtendAsync(request.GoodsId, goods.Type);

        // 6. 计算订单金额
        var result = await CalculateOrderAmountAsync(
            userId,
            user.Money,
            user.Integral,
            user.Money2 ?? 0,
            user.IsTest,
            goods.Id,
            goods.Type,
            goods.Price,
            goods.IsShouZhe,
            request.PrizeNum,
            request.UseMoneyIs,
            request.UseIntegralIs,
            request.UseMoney2Is,
            ParseCouponId(request.CouponId),
            goodsExtend
        );

        // 7. 构建响应（兼容 PHP 旧版字段名）
        return new OrderCalculationDto
        {
            OrderTotal = result.OrderTotal.ToString("0.00"),
            OrderZheTotal = result.OrderZheTotal.ToString("0.00"),
            Price = result.Price.ToString("0.00"),
            Zhe = result.Zhe.ToString("0.00"),
            // 用户余额信息（兼容旧版字段名）
            Money = user.Money.ToString("0.00"),
            Integral = user.Integral.ToString("0.00"),
            Score = user.Money2 ?? 0,
            // 使用金额信息
            UseMoney = result.UseMoney.ToString("0.00"),
            UseIntegral = result.UseIntegral.ToString("0.00"),
            UseIntegralMoney = (result.UseIntegral / 100).ToString("0.00"),
            UseScore = result.UseMoney2,
            UseMoney2 = result.UseMoney2,
            // 优惠券信息
            CouponId = result.CouponId,
            CouponPrice = result.CouponPrice.ToString("0.00"),
            IsShouZhe = result.IsShouZhe ? 1 : 0,
            // 商品信息（兼容旧版字段名 goods）
            Goods = new GoodsInfoDto
            {
                Id = goods.Id,
                Title = goods.Title,
                ImgUrlDetail = FormatImageUrl(goods.ImgUrlDetail),
                Price = goods.Price.ToString("0.##"),
                Type = goods.Type,
                IsShouZhe = goods.IsShouZhe,
                QuanjuXiangou = goods.QuanjuXiangou,
                DailyXiangou = goods.DailyXiangou,
                PrizeNum = request.PrizeNum,
                ShouZhePrice = result.ShouZhePrice.ToString("0.00")
            },
            GoodsExtend = goodsExtend
        };
    }

    /// <inheritdoc />
    public async Task<OrderCalculationDto> CalculateMallOrderMoneyAsync(int userId, MallOrderMoneyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.Money, u.Integral, u.Money2 })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 2. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .Select(g => new
            {
                g.Id,
                g.Title,
                g.ImgUrl,
                g.ImgUrlBanner,
                g.ImgUrlDetail,
                g.Type,
                g.Price,
                g.Stock,
                g.SaleStock,
                g.Status,
                g.IsShouZhe,
                g.GoodsDescribe
            })
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 3. 获取商品扩展配置
        var goodsExtend = await GetGoodsExtendAsync(request.GoodsId, goods.Type);

        // 3.1 查询 goods_items 汇总库存（商城赏的真实库存在 goods_items 表）
        var itemsStockSummary = await _dbContext.GoodsItems
            .Where(gi => gi.GoodsId == request.GoodsId)
            .GroupBy(gi => 1)
            .Select(g => new
            {
                TotalStock = g.Sum(x => x.Stock),
                SurplusStock = g.Sum(x => x.SurplusStock)
            })
            .FirstOrDefaultAsync();

        // 4. 计算价格
        // 商城订单使用积分(money2)支付，比例为1:100
        var price = goods.Price;
        var integral = price * 100; // 积分价格 = 单价 * 100
        var userMoney2 = user.Money2 ?? 0;

        // 5. 构建响应（兼容 PHP 旧版字段名）
        return new OrderCalculationDto
        {
            Price = price.ToString("0.00"),
            OrderTotal = price.ToString("0.00"),
            OrderZheTotal = price.ToString("0.00"),
            // 用户余额信息（兼容旧版字段名）
            Money = user.Money.ToString("0.00"),
            Integral = user.Integral.ToString("0.00"),
            Score = userMoney2,
            // 使用金额信息
            UseMoney = "0.00",
            UseIntegral = "0.00",
            UseIntegralMoney = "0.00",
            UseScore = integral, // 需要使用的积分数量
            UseMoney2 = integral,
            // 商品信息（兼容旧版字段名 goods）
            Goods = new GoodsInfoDto
            {
                Id = goods.Id,
                Title = goods.Title,
                ImgUrl = FormatImageUrl(goods.ImgUrl),
                ImgUrlBanner = FormatImageUrl(goods.ImgUrlBanner),
                ImgUrlDetail = FormatImageUrl(goods.ImgUrlDetail),
                Price = goods.Price.ToString("0.##"),
                Stock = goods.Stock,
                SaleStock = goods.SaleStock,
                SurplusStock = itemsStockSummary?.SurplusStock ?? (goods.Stock - goods.SaleStock),
                GoodslistStock = itemsStockSummary?.TotalStock ?? 0,
                GoodslistSurplusStock = itemsStockSummary?.SurplusStock ?? 0,
                Type = goods.Type,
                IsShouZhe = goods.IsShouZhe,
                PrizeNum = request.PrizeNum,
                GoodsDescribe = goods.GoodsDescribe
            },
            GoodsExtend = goodsExtend
        };
    }

    #endregion

    #region 订单创建

    /// <inheritdoc />
    public async Task<OrderBuyResponseDto> CreateOrderAsync(int userId, OrderBuyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new
            {
                u.Id,
                u.Mobile,
                u.OpenId,
                u.Money,
                u.Integral,
                u.Money2,
                u.IsTest
            })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 2. 验证手机号绑定
        if (string.IsNullOrEmpty(user.Mobile))
        {
            throw new InvalidOperationException("请先绑定手机号");
        }

        // 3. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 4. 获取商品扩展配置
        var goodsExtend = await GetGoodsExtendAsync(request.GoodsId, goods.Type);

        // 5. 验证箱号
        if (request.Num < 0 || request.Num > goods.Stock)
        {
            throw new InvalidOperationException("箱号选择错误");
        }

        // 6. 验证抽奖限制
        await ValidateDrawRestrictionsAsync(userId, goods.Id, goods.Type, goods.ChoujiangXianzhi,
            goods.QuanjuXiangou, goods.DailyXiangou, goods.FlwStartTime, goods.FlwEndTime, request.PrizeNum, user.IsTest);

        // 7. 验证奖品信息存在（非福利屋类型）
        var num = request.Num;
        if (goods.Type != 15)
        {
            var hasGoodsItems = await _dbContext.GoodsItems
                .AnyAsync(gi => gi.GoodsId == request.GoodsId
                    && gi.Num == num
                    && gi.ShangId >= ShangPrizeIdRange[0]
                    && gi.ShangId <= ShangPrizeIdRange[1]);

            if (!hasGoodsItems)
            {
                throw new InvalidOperationException("暂无奖品信息");
            }
        }
        else
        {
            num = 0;
        }

        // 8. 锁箱验证（一番赏、全局赏、追踪赏）
        if (goods.Type == 1 || goods.Type == 6 || goods.Type == 11)
        {
            var goodsIdNum = $"{request.GoodsId}_{num}";
            var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

            var lockInfo = await _dbContext.GoodsLocks
                .Where(gl => gl.GoodsIdNum == goodsIdNum && gl.EndTime > currentTime)
                .OrderByDescending(gl => gl.Id)
                .FirstOrDefaultAsync();

            if (lockInfo != null && lockInfo.EndTime > currentTime && lockInfo.UserId != userId)
            {
                var surplusTime = lockInfo.EndTime - currentTime;
                throw new InvalidOperationException($"有会员正在锁箱,请等待{surplusTime}秒");
            }
        }

        // 9. 擂台赏限购验证
        if (goods.Type == 3)
        {
            var hasOrderItem = await _dbContext.OrderItems
                .AnyAsync(oi => oi.GoodsId == request.GoodsId
                    && oi.UserId == userId
                    && oi.Num == num
                    && oi.OrderType == goods.Type
                    && oi.ShangId >= ShangPrizeIdRange[0]
                    && oi.ShangId <= ShangPrizeIdRange[1]);

            if (hasOrderItem)
            {
                throw new InvalidOperationException("限购一发");
            }
        }

        // 10. 验证库存（非福利屋类型）
        if (goods.Type != 15)
        {
            var stockInfo = await _dbContext.GoodsItems
                .Where(gi => gi.GoodsId == request.GoodsId
                    && gi.Num == num
                    && gi.ShangId >= ShangPrizeIdRange[0]
                    && gi.ShangId <= ShangPrizeIdRange[1])
                .SumAsync(gi => gi.SurplusStock);

            if (stockInfo <= 0)
            {
                throw new InvalidOperationException("库存剩余不足，请刷新重试");
            }

            if (request.PrizeNum <= 0)
            {
                throw new InvalidOperationException("抽奖数量选择错误,请刷新重试");
            }

            if (request.PrizeNum > stockInfo)
            {
                throw new InvalidOperationException("剩余数量不足，请刷新重试");
            }
        }

        // 11. 计算订单金额
        var paymentResult = await CalculateOrderAmountAsync(
            userId,
            user.Money,
            user.Integral,
            user.Money2 ?? 0,
            user.IsTest,
            goods.Id,
            goods.Type,
            goods.Price,
            goods.IsShouZhe,
            request.PrizeNum,
            request.UseMoneyIs,
            request.UseIntegralIs,
            request.UseMoney2Is,
            ParseCouponId(request.CouponId),
            goodsExtend
        );

        // 12. 处理锁箱（一番赏、全局赏、追踪赏）
        if (goods.Type == 1 || goods.Type == 6 || goods.Type == 11)
        {
            if (goods.LockIs == 1 && goods.LockTime.HasValue && goods.LockTime.Value > 0)
            {
                await HandleBoxLockingAsync(userId, request.GoodsId, num, request.PrizeNum, goods.LockTime.Value);
            }
        }

        // 13. 作废未支付订单（限购场景）
        var currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        if (goods.QuanjuXiangou > 0)
        {
            await _dbContext.Orders
                .Where(o => o.GoodsId == request.GoodsId
                    && o.UserId == userId
                    && o.Status == 0)
                .ExecuteUpdateAsync(s => s.SetProperty(o => o.Status, (byte)2));
        }

        if (goods.DailyXiangou > 0)
        {
            var oneDayAgo = currentTimestamp - 86400;
            await _dbContext.Orders
                .Where(o => o.GoodsId == request.GoodsId
                    && o.UserId == userId
                    && o.Status == 0
                    && o.Addtime >= oneDayAgo)
                .ExecuteUpdateAsync(s => s.SetProperty(o => o.Status, (byte)2));
        }

        // 14. 生成订单号
        var orderNum = GenerateOrderNum(goods.Type);

        // 15. 创建订单记录
        using var transaction = await _dbContext.Database.BeginTransactionAsync();
        try
        {
            var order = new Order
            {
                UserId = userId,
                OrderNum = orderNum,
                OrderTotal = paymentResult.OrderTotal,
                OrderZheTotal = paymentResult.OrderZheTotal,
                Price = paymentResult.Price,
                UseMoney = paymentResult.UseMoney,
                UseIntegral = paymentResult.UseIntegral,
                UseMoney2 = paymentResult.UseMoney2,
                UseScore = 0,
                Zhe = paymentResult.Zhe,
                GoodsId = request.GoodsId,
                Num = num,
                GoodsPrice = goods.Price,
                GoodsTitle = goods.Title,
                GoodsImgurl = goods.ImgUrlDetail,
                PrizeNum = request.PrizeNum,
                Status = 0,
                PayType = 1, // 微信支付
                OrderType = goods.Type,
                Addtime = (int)currentTimestamp,
                CouponId = paymentResult.CouponId > 0 ? paymentResult.CouponId : null,
                UseCoupon = paymentResult.CouponPrice,
                IsShouZhe = (byte)(paymentResult.IsShouZhe ? 1 : 0),
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now
            };

            _dbContext.Orders.Add(order);
            await _dbContext.SaveChangesAsync();

            // 16. 处理支付
            OrderBuyResponseDto response;

            if (paymentResult.Price > 0)
            {
                // 需要微信支付 - 调用微信支付服务
                var payRequest = new WechatPayRequest
                {
                    UserId = userId,
                    OrderNo = orderNum,
                    Amount = paymentResult.Price,
                    Body = goods.Title,
                    Attach = $"order_{goods.Type}"
                };

                var payResult = await _wechatPayService.CreatePaymentAsync(payRequest);

                if (payResult.Status != 1 || payResult.Data == null)
                {
                    // 支付创建失败，回滚事务
                    await transaction.RollbackAsync();
                    throw new InvalidOperationException(payResult.Msg ?? "创建支付订单失败");
                }

                response = new OrderBuyResponseDto
                {
                    Status = 1, // 需要支付
                    OrderNum = orderNum,
                    Res = new WechatPayParamsDto
                    {
                        AppId = payResult.Data.AppId,
                        TimeStamp = payResult.Data.TimeStamp,
                        NonceStr = payResult.Data.NonceStr,
                        Package = payResult.Data.Package,
                        SignType = payResult.Data.SignType,
                        PaySign = payResult.Data.PaySign
                    }
                };
            }
            else
            {
                // 余额/积分全额支付，直接标记为已支付
                order.Status = 1;
                order.PayTime = (int)currentTimestamp;

                // 扣减用户资产
                await DeductUserAssetsAsync(userId, paymentResult.UseMoney, paymentResult.UseIntegral, paymentResult.UseMoney2, goods.Title);

                // 使用优惠券
                if (paymentResult.CouponId > 0)
                {
                    await UseCouponAsync(paymentResult.CouponId);
                }

                await _dbContext.SaveChangesAsync();

                // 执行普通抽奖逻辑（一番赏等）
                await ExecuteLotteryAsync(userId, order.Id, request.GoodsId, goods.Type, num, request.PrizeNum, orderNum);

                response = new OrderBuyResponseDto
                {
                    Status = 0, // 已支付完成
                    OrderNum = orderNum,
                    Res = null
                };
            }

            await transaction.CommitAsync();
            return response;
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "创建订单失败: UserId={UserId}, GoodsId={GoodsId}", userId, request.GoodsId);
            throw new InvalidOperationException("购买失败,请刷新重试");
        }
    }

    /// <summary>
    /// 执行普通抽奖逻辑（一番赏、擂台赏、转转赏等）
    /// </summary>
    private async Task ExecuteLotteryAsync(int userId, int orderId, int goodsId, int orderType, int num, int prizeNum, string orderNum)
    {
        try
        {
            var drawRequest = new LotteryDrawRequest
            {
                UserId = userId,
                GoodsId = goodsId,
                Num = num,
                OrderId = orderId,
                OrderNum = orderNum,
                OrderType = orderType,
                Source = 1 // 抽奖获得
            };

            // 执行多次抽奖
            var results = await _lotteryEngine.DrawMultipleAsync(drawRequest, prizeNum);

            var successCount = results.Count(r => r.Success);
            _logger.LogInformation("普通抽奖完成: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}, Num={Num}, PrizeNum={PrizeNum}, SuccessCount={SuccessCount}",
                userId, orderId, goodsId, num, prizeNum, successCount);

            if (successCount == 0)
            {
                _logger.LogWarning("普通抽奖全部失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
                    userId, orderId, goodsId);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "执行普通抽奖失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
                userId, orderId, goodsId);
            // 抽奖失败不影响订单创建，但需要记录日志以便后续处理
        }
    }

    /// <summary>
    /// 生成订单号
    /// </summary>
    private static string GenerateOrderNum(int goodsType)
    {
        var prefix = goodsType switch
        {
            1 => "MH_YFS",  // 一番赏
            3 => "MH_LTS",  // 擂台赏
            5 => "MH_JFS",  // 积分赏
            6 => "MH_QJS",  // 全局赏
            10 => "MH_SCS", // 商城赏
            11 => "MH_ZZS", // 追踪赏
            15 => "MH_FLW", // 福利屋
            _ => "MH_QTS"   // 其他
        };

        var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
        var random = new Random().Next(1000, 9999);
        return $"{prefix}{timestamp}{random}";
    }

    /// <summary>
    /// 处理锁箱逻辑
    /// </summary>
    private async Task HandleBoxLockingAsync(int userId, int goodsId, int num, int prizeNum, int lockTime)
    {
        var goodsIdNum = $"{goodsId}_{num}";
        var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var defaultEndTime = currentTime + lockTime;

        // 获取时间配置
        var config = await GetBaseConfigAsync();
        var threeTime = config?.ThreeTime ?? 0;
        var fiveTime = config?.FiveTime ?? 0;

        // 计算结束时间
        long endTime = defaultEndTime;
        if (prizeNum == 3)
        {
            endTime = defaultEndTime + threeTime;
        }
        else if (prizeNum == 5)
        {
            endTime = defaultEndTime + fiveTime;
        }

        // 查找现有锁箱记录
        var existingLock = await _dbContext.GoodsLocks
            .Where(gl => gl.GoodsIdNum == goodsIdNum && gl.EndTime > currentTime)
            .OrderByDescending(gl => gl.Id)
            .FirstOrDefaultAsync();

        if (existingLock != null)
        {
            // 更新现有锁箱
            existingLock.EndTime = endTime;
            existingLock.UpdateTime = currentTime;
        }
        else
        {
            // 创建新锁箱
            var newLock = new GoodsLock
            {
                UserId = userId,
                GoodsIdNum = goodsIdNum,
                EndTime = endTime,
                UpdateTime = currentTime
            };
            _dbContext.GoodsLocks.Add(newLock);
        }

        await _dbContext.SaveChangesAsync();
    }

    /// <summary>
    /// 获取基础配置
    /// </summary>
    private async Task<BaseConfig?> GetBaseConfigAsync()
    {
        var configValue = await _dbContext.Configs
            .Where(c => c.ConfigKey == "base")
            .Select(c => c.ConfigValue)
            .FirstOrDefaultAsync();

        if (string.IsNullOrEmpty(configValue))
        {
            return null;
        }

        try
        {
            return System.Text.Json.JsonSerializer.Deserialize<BaseConfig>(configValue);
        }
        catch
        {
            return null;
        }
    }

    /// <summary>
    /// 扣减用户资产并记录流水
    /// </summary>
    private async Task DeductUserAssetsAsync(int userId, decimal useMoney, decimal useIntegral, decimal useMoney2, string goodsName = "")
    {
        var user = await _dbContext.Users.FindAsync(userId);
        if (user == null) return;

        var content = string.IsNullOrEmpty(goodsName) ? "抽奖消费" : $"抽奖消费-{goodsName}";

        // 扣减余额并记录流水
        if (useMoney > 0)
        {
            user.Money -= useMoney;
            _dbContext.ProfitMoneys.Add(new ProfitMoney
            {
                UserId = userId,
                ChangeMoney = -useMoney,
                Money = user.Money,
                Type = 3, // 消费
                Content = content,
                ShareUid = 0,
                CreatedAt = DateTime.Now
            });
        }

        // 扣减积分并记录流水
        if (useIntegral > 0)
        {
            user.Integral -= useIntegral;
            _dbContext.ProfitIntegrals.Add(new ProfitIntegral
            {
                UserId = userId,
                ChangeMoney = -useIntegral,
                Money = user.Integral,
                Type = 3, // 消费
                Content = content,
                ShareUid = 0,
                CreatedAt = DateTime.Now
            });
        }

        // 扣减钻石/哈尼券并记录流水
        if (useMoney2 > 0 && user.Money2.HasValue)
        {
            user.Money2 -= useMoney2;
            _dbContext.ProfitMoney2s.Add(new ProfitMoney2
            {
                UserId = userId,
                ChangeMoney = -useMoney2,
                Money = user.Money2 ?? 0,
                Type = 3, // 消费
                Content = content,
                ShareUid = 0,
                CreatedAt = DateTime.Now
            });
        }

        user.UpdatedAt = DateTime.Now;
    }

    /// <summary>
    /// 使用优惠券
    /// </summary>
    private async Task UseCouponAsync(int couponId)
    {
        var coupon = await _dbContext.CouponReceives.FindAsync(couponId);
        if (coupon != null)
        {
            coupon.Status = 1; // 已使用
        }
    }

    /// <summary>
    /// 基础配置类
    /// </summary>
    private class BaseConfig
    {
        public int ThreeTime { get; set; }
        public int FiveTime { get; set; }
    }

    /// <inheritdoc />
    public async Task<OrderBuyResponseDto> CreateInfiniteOrderAsync(int userId, InfiniteOrderBuyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new
            {
                u.Id,
                u.Mobile,
                u.OpenId,
                u.Money,
                u.Integral,
                u.Money2,
                u.IsTest,
                u.MbNumber,
                u.ClickId
            })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 2. 验证手机号绑定
        if (string.IsNullOrEmpty(user.Mobile))
        {
            throw new InvalidOperationException("请先绑定手机号");
        }

        // 3. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 4. 验证商品类型是否为无限赏类型
        if (!InfiniteGoodsTypes.Contains(goods.Type))
        {
            throw new InvalidOperationException("非法请求");
        }

        // 5. 获取商品扩展配置
        var goodsExtend = await GetGoodsExtendAsync(request.GoodsId, goods.Type);

        // 6. 验证抽奖限制
        await ValidateDrawRestrictionsAsync(userId, goods.Id, goods.Type, goods.ChoujiangXianzhi,
            goods.QuanjuXiangou, goods.DailyXiangou, goods.FlwStartTime, goods.FlwEndTime, request.PrizeNum, user.IsTest);

        // 7. 验证抽奖次数
        var prizeNum = request.PrizeNum;
        if (goods.Type == 9)
        {
            // 连击赏：最多20次
            if (prizeNum > 20)
            {
                throw new InvalidOperationException("一次最多购买20次");
            }
        }
        else
        {
            // 其他无限赏类型：只能是1、3、5、10
            if (prizeNum != 1 && prizeNum != 3 && prizeNum != 5 && prizeNum != 10)
            {
                throw new InvalidOperationException("请求参数错误!!!");
            }
        }

        // 8. 验证奖品信息存在
        var hasGoodsItems = await _dbContext.GoodsItems
            .AnyAsync(gi => gi.GoodsId == request.GoodsId
                && gi.Num == 0
                && gi.RealPro > 0
                && gi.ShangId >= InfiniteShangPrizeIdRange[0]
                && gi.ShangId <= InfiniteShangPrizeIdRange[1]);

        if (!hasGoodsItems)
        {
            throw new InvalidOperationException("暂无奖品信息");
        }

        // 9. 计算订单金额
        var paymentResult = await CalculateOrderAmountAsync(
            userId,
            user.Money,
            user.Integral,
            user.Money2 ?? 0,
            user.IsTest,
            goods.Id,
            goods.Type,
            goods.Price,
            goods.IsShouZhe,
            prizeNum,
            request.UseMoneyIs,
            request.UseIntegralIs,
            request.UseMoney2Is,
            ParseCouponId(request.CouponId),
            goodsExtend
        );

        // 10. 作废未支付订单（限购场景）
        var currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        if (goods.QuanjuXiangou > 0)
        {
            await _dbContext.Orders
                .Where(o => o.GoodsId == request.GoodsId
                    && o.UserId == userId
                    && o.Status == 0)
                .ExecuteUpdateAsync(s => s.SetProperty(o => o.Status, (byte)2));
        }

        if (goods.DailyXiangou > 0)
        {
            var oneDayAgo = currentTimestamp - 86400;
            await _dbContext.Orders
                .Where(o => o.GoodsId == request.GoodsId
                    && o.UserId == userId
                    && o.Status == 0
                    && o.Addtime >= oneDayAgo)
                .ExecuteUpdateAsync(s => s.SetProperty(o => o.Status, (byte)2));
        }

        // 11. 生成订单号
        var orderNum = GenerateInfiniteOrderNum(goods.Type);

        // 12. 创建订单记录
        using var transaction = await _dbContext.Database.BeginTransactionAsync();
        try
        {
            var order = new Order
            {
                UserId = userId,
                OrderNum = orderNum,
                OrderTotal = paymentResult.OrderTotal,
                OrderZheTotal = paymentResult.OrderZheTotal,
                Price = paymentResult.Price,
                UseMoney = paymentResult.UseMoney,
                UseIntegral = paymentResult.UseIntegral,
                UseMoney2 = paymentResult.UseMoney2,
                UseScore = 0,
                Zhe = paymentResult.Zhe,
                GoodsId = request.GoodsId,
                Num = 0, // 无限赏固定为0
                GoodsPrice = goods.Price,
                GoodsTitle = goods.Title,
                GoodsImgurl = goods.ImgUrlDetail,
                PrizeNum = prizeNum,
                Status = 0,
                PayType = 1, // 微信支付
                OrderType = goods.Type,
                Addtime = (int)currentTimestamp,
                CouponId = paymentResult.CouponId > 0 ? paymentResult.CouponId : null,
                UseCoupon = paymentResult.CouponPrice,
                IsShouZhe = (byte)(paymentResult.IsShouZhe ? 1 : 0),
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now
            };

            _dbContext.Orders.Add(order);
            await _dbContext.SaveChangesAsync();

            // 13. 处理支付
            OrderBuyResponseDto response;

            if (paymentResult.Price > 0)
            {
                // 需要微信支付 - 调用微信支付服务
                var payRequest = new WechatPayRequest
                {
                    UserId = userId,
                    OrderNo = orderNum,
                    Amount = paymentResult.Price,
                    Body = goods.Title,
                    Attach = $"infinite_{goods.Type}"
                };

                var payResult = await _wechatPayService.CreatePaymentAsync(payRequest);

                if (payResult.Status != 1 || payResult.Data == null)
                {
                    // 支付创建失败，回滚事务
                    await transaction.RollbackAsync();
                    throw new InvalidOperationException(payResult.Msg ?? "创建支付订单失败");
                }

                response = new OrderBuyResponseDto
                {
                    Status = 1, // 需要支付
                    OrderNum = orderNum,
                    Res = new WechatPayParamsDto
                    {
                        AppId = payResult.Data.AppId,
                        TimeStamp = payResult.Data.TimeStamp,
                        NonceStr = payResult.Data.NonceStr,
                        Package = payResult.Data.Package,
                        SignType = payResult.Data.SignType,
                        PaySign = payResult.Data.PaySign
                    }
                };
            }
            else
            {
                // 余额/积分全额支付，直接标记为已支付
                order.Status = 1;
                order.PayTime = (int)currentTimestamp;

                // 扣减用户资产
                await DeductUserAssetsAsync(userId, paymentResult.UseMoney, paymentResult.UseIntegral, paymentResult.UseMoney2, goods.Title);

                // 使用优惠券
                if (paymentResult.CouponId > 0)
                {
                    await UseCouponAsync(paymentResult.CouponId);
                }

                await _dbContext.SaveChangesAsync();

                // 执行无限赏抽奖逻辑
                await ExecuteInfiniteLotteryAsync(userId, order.Id, request.GoodsId, goods.Type, prizeNum, orderNum);

                response = new OrderBuyResponseDto
                {
                    Status = 0, // 已支付完成
                    OrderNum = orderNum,
                    Res = null
                };
            }

            await transaction.CommitAsync();
            return response;
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "创建无限赏订单失败: UserId={UserId}, GoodsId={GoodsId}", userId, request.GoodsId);
            throw new InvalidOperationException("购买失败,请刷新重试");
        }
    }

    /// <summary>
    /// 执行无限赏抽奖逻辑
    /// </summary>
    private async Task ExecuteInfiniteLotteryAsync(int userId, int orderId, int goodsId, int orderType, int prizeNum, string orderNum)
    {
        try
        {
            var drawRequest = new LotteryDrawRequest
            {
                UserId = userId,
                GoodsId = goodsId,
                Num = 0, // 无限赏固定为0
                OrderId = orderId,
                OrderNum = orderNum,
                OrderType = orderType,
                Source = 1 // 抽奖获得
            };

            // 执行多次抽奖
            var results = await _lotteryEngine.DrawInfiniteMultipleAsync(drawRequest, prizeNum);

            var successCount = results.Count(r => r.Success);
            _logger.LogInformation("无限赏抽奖完成: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}, PrizeNum={PrizeNum}, SuccessCount={SuccessCount}",
                userId, orderId, goodsId, prizeNum, successCount);

            if (successCount == 0)
            {
                _logger.LogWarning("无限赏抽奖全部失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
                    userId, orderId, goodsId);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "执行无限赏抽奖失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
                userId, orderId, goodsId);
            // 抽奖失败不影响订单创建，但需要记录日志以便后续处理
        }
    }

    /// <summary>
    /// 生成无限赏订单号
    /// </summary>
    private static string GenerateInfiniteOrderNum(int goodsType)
    {
        var prefix = goodsType switch
        {
            2 => "MH_WXS",   // 无限赏
            8 => "MH_WXS8",  // 无限赏类型8
            9 => "MH_LJS",   // 连击赏
            10 => "MH_SCS",  // 商城赏
            16 => "MH_FBS",  // 福袋赏
            17 => "MH_WXS17", // 无限赏类型17
            _ => "MH_WXS"    // 默认无限赏
        };

        var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
        var random = new Random().Next(1000, 9999);
        return $"{prefix}{timestamp}{random}";
    }

    #endregion

    #region 订单查询

    /// <inheritdoc />
    public async Task<PageResponse<OrderListDto>> GetOrderListAsync(int userId, OrderListRequest request)
    {
        // 1. 构建查询条件
        var query = _dbContext.Orders
            .Where(o => o.UserId == userId && o.Status == 1)
            .OrderByDescending(o => o.Addtime);

        // 2. 获取总数
        var total = await query.CountAsync();

        // 3. 计算分页
        var page = request.Page > 0 ? request.Page : 1;
        var pageSize = request.PageSize > 0 ? request.PageSize : 10;
        var lastPage = (int)Math.Ceiling((double)total / pageSize);

        // 4. 获取分页数据
        var orders = await query
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(o => new OrderListDto
            {
                Id = o.Id,
                OrderNum = o.OrderNum,
                GoodsTitle = o.GoodsTitle ?? string.Empty,
                GoodsImgUrl = o.GoodsImgurl ?? string.Empty,
                OrderTotal = o.OrderTotal.ToString("0.00"),
                OrderZheTotal = o.OrderZheTotal.ToString("0.00"),
                Price = o.Price.ToString("0.00"),
                PrizeNum = o.PrizeNum,
                Status = o.Status,
                AddTime = o.Addtime,
                PayTime = o.PayTime > 0 ? o.PayTime : null,
                OrderType = o.OrderType
            })
            .ToListAsync();

        // 5. 格式化图片URL
        foreach (var order in orders)
        {
            order.GoodsImgUrl = FormatImageUrl(order.GoodsImgUrl);
        }

        // 6. 返回分页响应
        return new PageResponse<OrderListDto>
        {
            Data = orders,
            Total = total,
            Page = page,
            PageSize = pageSize,
            LastPage = lastPage
        };
    }

    /// <inheritdoc />
    public async Task<OrderInfoDto> GetOrderDetailAsync(int userId, string orderNum)
    {
        // 1. 验证订单号
        if (string.IsNullOrEmpty(orderNum))
        {
            throw new InvalidOperationException("订单编号不能为空");
        }

        // 2. 查询订单信息
        var order = await _dbContext.Orders
            .Where(o => o.OrderNum == orderNum && o.Status == 1)
            .FirstOrDefaultAsync();

        if (order == null)
        {
            throw new InvalidOperationException("订单不存在");
        }

        // 3. 查询订单商品列表（奖品列表）
        var goodsList = await _dbContext.OrderItems
            .Where(oi => oi.OrderId == order.Id)
            .Select(oi => new OrderGoodsItemDto
            {
                GoodsListTitle = oi.GoodslistTitle ?? string.Empty,
                GoodsListImgUrl = oi.GoodslistImgurl ?? string.Empty,
                GoodsListPrice = oi.GoodslistPrice,
                AddTime = DateTimeOffset.FromUnixTimeSeconds(oi.Addtime).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss")
            })
            .ToListAsync();

        // 4. 格式化奖品图片URL
        foreach (var item in goodsList)
        {
            item.GoodsListImgUrl = FormatImageUrl(item.GoodsListImgUrl);
        }

        // 5. 构建扁平结构的订单详情（与PHP旧版一致）
        return new OrderInfoDto
        {
            Id = order.Id,
            OrderNum = order.OrderNum,
            GoodsId = order.GoodsId,
            GoodsTitle = order.GoodsTitle ?? string.Empty,
            GoodsImgUrl = FormatImageUrl(order.GoodsImgurl),
            GoodsPrice = order.GoodsPrice.ToString("0.00"),
            OrderTotal = order.OrderTotal.ToString("0.00"),
            OrderZheTotal = order.OrderZheTotal.ToString("0.00"),
            Price = order.Price.ToString("0.00"),
            UseMoney = order.UseMoney.ToString("0.00"),
            UseIntegral = order.UseIntegral.ToString("0.00"),
            UseMoney2 = order.UseMoney2.ToString("0.00"),
            UseCoupon = (order.UseCoupon ?? 0).ToString("0.00"),
            PrizeNum = order.PrizeNum,
            Status = order.Status,
            AddTime = order.Addtime,
            PayTime = order.PayTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(order.PayTime).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss") : null,
            OrderType = order.OrderType,
            GoodsList = goodsList
        };
    }

    #endregion

    #region 抽奖结果查询

    /// <inheritdoc />
    public async Task<PrizeOrderLogResponseDto> GetPrizeOrderLogAsync(int userId, string orderNum)
    {
        // 1. 获取订单信息
        var orderInfo = await _dbContext.Orders
            .Where(o => o.OrderNum == orderNum && o.UserId == userId)
            .Select(o => new { o.Id, o.GoodsId, o.Num, o.OrderType, o.PrizeNum })
            .FirstOrDefaultAsync();

        if (orderInfo == null)
        {
            throw new InvalidOperationException("支付异常,请刷新重试");
        }

        // 2. 获取用户欧气券信息
        var userCoupon = await _dbContext.UserCoupons
            .Where(uc => uc.UserId == userId && uc.FromId == orderInfo.Id.ToString())
            .OrderByDescending(uc => uc.Level)
            .Select(uc => new { uc.Id, uc.Level, uc.Title, uc.Num })
            .FirstOrDefaultAsync();

        UserCouponInfoDto? userCouponDto = null;
        if (userCoupon != null)
        {
            userCouponDto = new UserCouponInfoDto
            {
                Id = userCoupon.Id,
                Level = userCoupon.Level ?? 0,
                Title = userCoupon.Title,
                Num = userCoupon.Num,
                LevelText = GetCouponLevelText(userCoupon.Level ?? 0),
                LevelImg = GetCouponLevelImg(userCoupon.Level ?? 0)
            };
        }

        // 3. 获取奖品列表（按prize_code分组，按shang_id和id排序）
        var prizeList = await _dbContext.OrderItems
            .Where(oi => oi.UserId == userId && oi.OrderId == orderInfo.Id && oi.OrderType == orderInfo.OrderType)
            .GroupBy(oi => oi.PrizeCode)
            .Select(g => new PrizeOrderLogDto
            {
                Id = g.First().Id,
                UserId = g.First().UserId,
                ShangId = g.First().ShangId,
                GoodsListId = g.First().GoodslistId,
                GoodsListTitle = g.First().GoodslistTitle ?? string.Empty,
                GoodsListImgUrl = g.First().GoodslistImgurl ?? string.Empty,
                GoodsListMoney = g.First().GoodslistMoney.ToString("0.00"),
                GoodsListPrice = g.First().GoodslistPrice.ToString("0.00"),
                Doubling = g.First().Doubling,
                IsLingzhu = g.First().IsLingzhu,
                GoodsListType = g.First().GoodslistType,
                ParentGoodsListId = g.First().ParentGoodsListId,
                PrizeNum = g.Count(),
                Status = g.First().Status,
                LuckNo = g.First().LuckNo,
                AddTime = g.First().Addtime
            })
            .OrderBy(p => p.ShangId)
            .ThenBy(p => p.Id)
            .ToListAsync();

        // 4. 获取赏品等级信息
        var shangIds = prizeList.Select(p => p.ShangId).Distinct().ToList();
        var shangInfos = await _dbContext.PrizeLevels
            .Where(pl => shangIds.Contains(pl.Id))
            .ToDictionaryAsync(pl => pl.Id, pl => new ShangInfoDto
            {
                Id = pl.Id,
                Title = pl.Title,
                ImgUrl = FormatImageUrl(pl.ImgUrl),
                Color = pl.Color,
                SpecialImgUrl = FormatImageUrl(pl.SpecialImgUrl)
            });

        // 5. 填充赏品等级信息和格式化图片URL
        foreach (var prize in prizeList)
        {
            prize.GoodsListImgUrl = FormatImageUrl(prize.GoodsListImgUrl);
            if (shangInfos.TryGetValue(prize.ShangId, out var shangInfo))
            {
                prize.ShangInfo = shangInfo;
                prize.ShangTitle = shangInfo.Title;
            }
        }

        // 6. 获取重抽卡数量
        // 注：PHP代码中查询的是user_item_card表，这里暂时返回0
        var itemCardCount = 0;

        return new PrizeOrderLogResponseDto
        {
            Data = prizeList,
            ItemCardCount = itemCardCount,
            UserCoupon = userCouponDto,
            PrizeNum = orderInfo.PrizeNum
        };
    }

    /// <inheritdoc />
    public async Task<InfinitePrizeOrderLogResponseDto> GetInfinitePrizeOrderLogAsync(int userId, string orderNum)
    {
        // 1. 获取订单信息
        var orderInfo = await _dbContext.Orders
            .Where(o => o.OrderNum == orderNum && o.UserId == userId)
            .Select(o => new { o.Id, o.GoodsId, o.Num, o.OrderType, o.PrizeNum })
            .FirstOrDefaultAsync();

        if (orderInfo == null)
        {
            throw new InvalidOperationException("支付异常,请刷新重试");
        }

        // 2. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Nickname, u.HeadImg })
            .FirstOrDefaultAsync();

        var userInfo = user != null ? new UserBasicInfoDto
        {
            Nickname = user.Nickname ?? string.Empty,
            HeadImg = FormatImageUrl(user.HeadImg)
        } : null;

        // 3. 获取奖品列表（按goodslist_money降序，id升序排序）
        var prizeList = await _dbContext.OrderItems
            .Where(oi => oi.UserId == userId && oi.OrderId == orderInfo.Id && oi.OrderType == orderInfo.OrderType)
            .OrderByDescending(oi => oi.GoodslistMoney)
            .ThenBy(oi => oi.Id)
            .Select(oi => new PrizeOrderLogDto
            {
                Id = oi.Id,
                UserId = oi.UserId,
                ShangId = oi.ShangId,
                GoodsListId = oi.GoodslistId,
                GoodsListTitle = oi.GoodslistTitle ?? string.Empty,
                GoodsListImgUrl = oi.GoodslistImgurl ?? string.Empty,
                GoodsListMoney = oi.GoodslistMoney.ToString("0.00"),
                GoodsListPrice = oi.GoodslistPrice.ToString("0.00"),
                Doubling = oi.Doubling,
                IsLingzhu = oi.IsLingzhu,
                GoodsListType = oi.GoodslistType,
                ParentGoodsListId = oi.ParentGoodsListId,
                PrizeNum = 1,
                Status = oi.Status,
                LuckNo = oi.LuckNo,
                AddTime = oi.Addtime
            })
            .ToListAsync();

        // 4. 获取赏品等级信息
        var shangIds = prizeList.Select(p => p.ShangId).Distinct().ToList();
        var shangInfos = await _dbContext.PrizeLevels
            .Where(pl => shangIds.Contains(pl.Id))
            .ToDictionaryAsync(pl => pl.Id, pl => new ShangInfoDto
            {
                Id = pl.Id,
                Title = pl.Title,
                ImgUrl = FormatImageUrl(pl.ImgUrl),
                Color = pl.Color,
                SpecialImgUrl = FormatImageUrl(pl.SpecialImgUrl)
            });

        // 5. 填充赏品等级信息和格式化图片URL
        foreach (var prize in prizeList)
        {
            prize.GoodsListImgUrl = FormatImageUrl(prize.GoodsListImgUrl);
            if (shangInfos.TryGetValue(prize.ShangId, out var shangInfo))
            {
                prize.ShangInfo = shangInfo;
                prize.ShangTitle = shangInfo.Title;
            }
        }

        // 6. 获取用户欧气券信息
        var userCoupon = await _dbContext.UserCoupons
            .Where(uc => uc.UserId == userId && uc.FromId == orderInfo.Id.ToString())
            .OrderByDescending(uc => uc.Level)
            .Select(uc => new { uc.Id, uc.Level, uc.Title, uc.Num })
            .FirstOrDefaultAsync();

        UserCouponInfoDto? userCouponDto = null;
        if (userCoupon != null)
        {
            userCouponDto = new UserCouponInfoDto
            {
                Id = userCoupon.Id,
                Level = userCoupon.Level ?? 0,
                Title = userCoupon.Title,
                Num = userCoupon.Num,
                LevelText = GetCouponLevelText(userCoupon.Level ?? 0),
                LevelImg = GetCouponLevelImg(userCoupon.Level ?? 0)
            };
        }

        // 7. 无限赏的重抽卡数量固定为0
        var itemCardCount = 0;

        return new InfinitePrizeOrderLogResponseDto
        {
            UserInfo = userInfo,
            Data = prizeList,
            ItemCardCount = itemCardCount,
            UserCoupon = userCouponDto,
            PrizeNum = orderInfo.PrizeNum
        };
    }

    /// <summary>
    /// 获取欧气券等级文本
    /// </summary>
    private static string GetCouponLevelText(int level)
    {
        return level switch
        {
            1 => "特级赏券",
            2 => "终极赏券",
            3 => "高级赏券",
            4 => "普通赏券",
            _ => string.Empty
        };
    }

    /// <summary>
    /// 获取欧气券等级图片
    /// </summary>
    private static string GetCouponLevelImg(int level)
    {
        return level switch
        {
            1 => "/storage/coupon/coupon_a.png",
            2 => "/storage/coupon/coupon_b.png",
            3 => "/storage/coupon/coupon_c.png",
            4 => "/storage/coupon/coupon_d.png",
            _ => string.Empty
        };
    }

    #endregion

    #region 订单模块扩展

    /// <inheritdoc />
    public async Task<OrderStatusResponseDto> GetOrderStatusAsync(int userId, string orderNum)
    {
        if (string.IsNullOrEmpty(orderNum))
        {
            throw new InvalidOperationException("订单编号不能为空");
        }

        var orderNotify = await _dbContext.OrderNotifies
            .Where(on => on.OrderNo == orderNum)
            .FirstOrDefaultAsync();

        if (orderNotify == null)
        {
            throw new InvalidOperationException("订单不存在");
        }

        var message = orderNotify.Status switch
        {
            1 => "支付成功",
            2 => "订单已失效",
            _ => "支付未完成，请10秒后重试！"
        };

        return new OrderStatusResponseDto
        {
            Status = orderNotify.Status,
            Message = message
        };
    }

    /// <inheritdoc />
    public async Task<GetOrderListResponseDto> GetOrderListByGetAsync(int userId, int page, int pageSize)
    {
        if (page < 1) page = 1;
        if (pageSize < 1) pageSize = 10;

        var query = _dbContext.Orders
            .Where(o => o.UserId == userId && o.Status == 1)
            .OrderByDescending(o => o.Addtime);

        var total = await query.CountAsync();
        var totalPages = (int)Math.Ceiling((double)total / pageSize);

        var orders = await query
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(o => new OrderListItemDto
            {
                GoodsId = o.GoodsId,
                GoodsTitle = o.GoodsTitle ?? string.Empty,
                GoodsPrice = o.GoodsPrice,
                OrderTotal = o.OrderTotal,
                OrderZheTotal = o.OrderZheTotal,
                Price = o.Price,
                UseMoney = o.UseMoney,
                UseIntegral = o.UseIntegral,
                UseMoney2 = o.UseMoney2,
                PrizeNum = o.PrizeNum,
                UseCoupon = o.UseCoupon ?? 0,
                OrderNum = o.OrderNum
            })
            .ToListAsync();

        // 格式化时间
        var orderIds = orders.Select(o => o.OrderNum).ToList();
        var orderTimes = await _dbContext.Orders
            .Where(o => orderIds.Contains(o.OrderNum))
            .Select(o => new { o.OrderNum, o.Addtime, o.PayTime })
            .ToListAsync();

        foreach (var order in orders)
        {
            var times = orderTimes.FirstOrDefault(t => t.OrderNum == order.OrderNum);
            if (times != null)
            {
                order.Addtime = DateTimeOffset.FromUnixTimeSeconds(times.Addtime).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss");
                order.PayTime = times.PayTime > 0 
                    ? DateTimeOffset.FromUnixTimeSeconds(times.PayTime).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss") 
                    : string.Empty;
            }
        }

        return new GetOrderListResponseDto
        {
            List = orders,
            Total = total,
            Page = page,
            PageSize = pageSize,
            TotalPages = totalPages
        };
    }

    /// <inheritdoc />
    public async Task<WebPayOrderResponseDto> CreateWebPayOrderAsync(int userId, string orderNum)
    {
        if (string.IsNullOrEmpty(orderNum))
        {
            throw new InvalidOperationException("订单编号不能为空");
        }

        // 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.OpenId })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 获取订单通知记录
        var orderNotify = await _dbContext.OrderNotifies
            .Where(on => on.OrderNo == orderNum)
            .FirstOrDefaultAsync();

        if (orderNotify == null)
        {
            throw new InvalidOperationException("订单不存在");
        }

        if (orderNotify.Status == 1)
        {
            throw new InvalidOperationException("订单已支付");
        }

        if (orderNotify.Status == 2)
        {
            throw new InvalidOperationException("订单已失效");
        }

        // TODO: 实际实现需要调用微信支付API生成H5支付链接
        // 这里返回占位数据
        return new WebPayOrderResponseDto
        {
            PayUrl = $"https://pay.example.com/h5pay?order_num={orderNum}",
            OrderNum = orderNum
        };
    }

    /// <inheritdoc />
    public async Task<OrderUrlLinkResponseDto> GetOrderUrlLinkAsync(string orderNum)
    {
        if (string.IsNullOrEmpty(orderNum))
        {
            throw new InvalidOperationException("订单编号不能为空");
        }

        var orderNotify = await _dbContext.OrderNotifies
            .Where(on => on.OrderNo == orderNum)
            .FirstOrDefaultAsync();

        if (orderNotify == null)
        {
            throw new InvalidOperationException("未找到订单");
        }

        if (orderNotify.Status == 2)
        {
            throw new InvalidOperationException("订单已失效");
        }

        if (string.IsNullOrEmpty(orderNotify.Extend))
        {
            throw new InvalidOperationException("订单号错误");
        }

        // TODO: 实际实现需要调用微信小程序API生成URL Link
        // 这里返回占位数据
        return new OrderUrlLinkResponseDto
        {
            UrlLink = $"https://wxaurl.cn/placeholder_{orderNum}"
        };
    }

    /// <inheritdoc />
    public async Task<OrderBuyResponseDto> CreateMallOrderAsync(int userId, MallOrderBuyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.Mobile, u.Money2 })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        if (string.IsNullOrEmpty(user.Mobile))
        {
            throw new InvalidOperationException("请先绑定手机号");
        }

        // 2. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .Select(g => new
            {
                g.Id,
                g.Title,
                g.ImgUrlDetail,
                g.Type,
                g.Price,
                g.Status,
                g.ChoujiangXianzhi,
                g.DailyXiangou
            })
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 3. 验证商品类型（商城类型：2, 8, 9, 10）
        if (!new[] { 2, 8, 9, 10 }.Contains(goods.Type))
        {
            throw new InvalidOperationException("非法请求");
        }

        // 4. 验证抽奖门槛
        if (goods.ChoujiangXianzhi > 0)
        {
            var userPrice = await _dbContext.Orders
                .Where(o => o.Status == 1 && o.UserId == userId)
                .SumAsync(o => o.Price);
            var userUseMoney = await _dbContext.Orders
                .Where(o => o.Status == 1 && o.UserId == userId)
                .SumAsync(o => o.UseMoney);

            var totalSpent = userPrice + userUseMoney;
            if (totalSpent < goods.ChoujiangXianzhi)
            {
                throw new InvalidOperationException($"消费满{goods.ChoujiangXianzhi}元可参与 已消费{Math.Round(totalSpent, 2)}元");
            }
        }

        // 5. 验证每日限购
        if (goods.DailyXiangou > 0)
        {
            var todayStart = DateTime.Today;
            var todayStartTimestamp = new DateTimeOffset(todayStart).ToUnixTimeSeconds();
            var todayEndTimestamp = new DateTimeOffset(todayStart.AddDays(1)).ToUnixTimeSeconds();

            var todayBuyCount = await _dbContext.Orders
                .Where(o => o.UserId == userId
                    && o.GoodsId == request.GoodsId
                    && o.Status == 1
                    && o.Addtime >= todayStartTimestamp
                    && o.Addtime < todayEndTimestamp)
                .CountAsync();

            if (todayBuyCount >= goods.DailyXiangou)
            {
                throw new InvalidOperationException($"该商品每日限购{goods.DailyXiangou}次，今日已购买{todayBuyCount}次");
            }
        }

        // 5.1 验证全局商城每日购买次数限制
        var exchangeTimes = await GetExchangeTimesLimitAsync();
        if (exchangeTimes > 0)
        {
            var todayStart2 = DateTime.Today;
            var todayStartTimestamp2 = new DateTimeOffset(todayStart2).ToUnixTimeSeconds();
            var todayEndTimestamp2 = new DateTimeOffset(todayStart2.AddDays(1)).ToUnixTimeSeconds();

            // 统计用户今日在商城（type=10）的购买次数
            var todayMallBuyCount = await _dbContext.Orders
                .Where(o => o.UserId == userId
                    && o.OrderType == 10
                    && o.Status == 1
                    && o.Addtime >= todayStartTimestamp2
                    && o.Addtime < todayEndTimestamp2)
                .CountAsync();

            if (todayMallBuyCount >= exchangeTimes)
            {
                throw new InvalidOperationException($"商城每日限购{exchangeTimes}次，今日已购买{todayMallBuyCount}次");
            }
        }

        // 6. 验证抽奖次数
        if (request.PrizeNum != 1 && request.PrizeNum != 3 && request.PrizeNum != 5 && request.PrizeNum != 10 && request.PrizeNum != 50)
        {
            throw new InvalidOperationException("请求参数错误!!!");
        }

        // 7. 计算所需积分（1:100比例）
        var orderTotal = goods.Price * 100;
        var userMoney2 = user.Money2 ?? 0;

        if (orderTotal > userMoney2)
        {
            throw new InvalidOperationException("余额不足!!!");
        }

        // 8. 生成订单号
        var orderNum = $"MH_SC{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";
        var currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

        // 9. 创建订单
        using var transaction = await _dbContext.Database.BeginTransactionAsync();
        try
        {
            var num = goods.Type == 10 ? 1 : 0;

            var order = new Order
            {
                UserId = userId,
                OrderNum = orderNum,
                OrderTotal = goods.Price,
                OrderZheTotal = 0,
                Price = 0,
                UseMoney = 0,
                UseIntegral = 0,
                UseMoney2 = orderTotal,
                UseScore = 0,
                Zhe = 0,
                GoodsId = request.GoodsId,
                Num = num,
                GoodsPrice = goods.Price,
                GoodsTitle = goods.Title,
                GoodsImgurl = goods.ImgUrlDetail,
                PrizeNum = request.PrizeNum,
                Status = 0,
                PayType = 1,
                OrderType = goods.Type,
                Addtime = (int)currentTimestamp,
                CouponId = null,
                UseCoupon = 0,
                IsMibao = 0,
                IsShouZhe = 0,
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now
            };

            _dbContext.Orders.Add(order);
            await _dbContext.SaveChangesAsync();

            // 10. 扣减用户积分
            var userEntity = await _dbContext.Users.FindAsync(userId);
            if (userEntity != null && userEntity.Money2.HasValue)
            {
                userEntity.Money2 -= orderTotal;
                userEntity.UpdatedAt = DateTime.Now;
            }

            // 11. 执行商城抽奖 - 查找奖品并发放
            // 商城类型(type=10)的奖品 num=1
            var prizeItem = await _dbContext.GoodsItems
                .Where(g => g.GoodsId == request.GoodsId && g.Num == num && g.SurplusStock > 0)
                .FirstOrDefaultAsync();

            if (prizeItem == null)
            {
                throw new InvalidOperationException("库存不足，兑换失败");
            }

            // 12. 扣减奖品库存
            prizeItem.SurplusStock -= 1;
            prizeItem.UpdatedAt = DateTime.Now;

            // 13. 获取当前奖品的luck_no
            var luckNo = await _dbContext.OrderItems
                .Where(o => o.GoodsId == request.GoodsId && o.Num == num && o.OrderType == goods.Type)
                .OrderByDescending(o => o.Id)
                .Select(o => o.LuckNo)
                .FirstOrDefaultAsync();
            luckNo++;

            // 14. 创建中奖记录 (OrderList/OrderItem)
            var saleTimeStamp = prizeItem.SaleTime.HasValue 
                ? (int)new DateTimeOffset(prizeItem.SaleTime.Value).ToUnixTimeSeconds() 
                : 0;

            var orderItem = new OrderItem
            {
                OrderId = order.Id,
                UserId = userId,
                Status = 0, // 0-未操作
                GoodsId = request.GoodsId,
                Num = num,
                ShangId = prizeItem.ShangId ?? 0,
                GoodslistId = prizeItem.Id,
                GoodslistTitle = prizeItem.Title,
                GoodslistImgurl = prizeItem.ImgUrl,
                GoodslistPrice = prizeItem.Price,
                GoodslistMoney = prizeItem.Money,
                GoodslistType = prizeItem.GoodsType,
                GoodslistSaleTime = saleTimeStamp,
                Addtime = (int)currentTimestamp,
                PrizeCode = prizeItem.PrizeCode ?? "",
                OrderType = goods.Type,
                LuckNo = luckNo,
                ParentGoodsListId = 0,
                ChoiceTime = 0,
                FhStatus = 0,
                IsChong = 0,
                IsLingzhu = 0
            };

            _dbContext.OrderItems.Add(orderItem);

            // 15. 扣减商品库存（增加已售数量）
            var goodsEntity = await _dbContext.Goods.FindAsync(request.GoodsId);
            if (goodsEntity != null)
            {
                goodsEntity.SaleStock += 1;
                goodsEntity.UpdatedAt = DateTime.Now;
            }

            // 16. 标记订单为已支付
            order.Status = 1;
            order.PayTime = (int)currentTimestamp;

            await _dbContext.SaveChangesAsync();
            await transaction.CommitAsync();

            return new OrderBuyResponseDto
            {
                Status = 0,
                OrderNum = orderNum,
                Res = null
            };
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "创建商城订单失败: UserId={UserId}, GoodsId={GoodsId}", userId, request.GoodsId);
            throw new InvalidOperationException("购买失败,请刷新重试");
        }
    }

    /// <inheritdoc />
    public async Task<ItemCardListResponseDto> GetItemCardListAsync(int userId, int page, int pageSize)
    {
        if (page < 1) page = 1;
        if (pageSize < 1) pageSize = 20;

        var query = _dbContext.UserItemCards
            .Where(c => c.UserId == userId && c.Status == 1)
            .OrderByDescending(c => c.Id);

        var total = await query.CountAsync();
        var lastPage = (int)Math.Ceiling((double)total / pageSize);

        var items = await query
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(c => new OrderItemCardDto
            {
                Id = c.Id,
                Type = c.Type,
                Title = c.Title,
                Addtime = string.Empty
            })
            .ToListAsync();

        // 格式化时间
        var itemIds = items.Select(i => i.Id).ToList();
        var itemTimes = await _dbContext.UserItemCards
            .Where(c => itemIds.Contains(c.Id))
            .Select(c => new { c.Id, c.Addtime })
            .ToListAsync();

        foreach (var item in items)
        {
            var time = itemTimes.FirstOrDefault(t => t.Id == item.Id);
            if (time != null)
            {
                item.Addtime = DateTimeOffset.FromUnixTimeSeconds(time.Addtime).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss");
            }
        }

        return new ItemCardListResponseDto
        {
            List = items,
            Count = total,
            LastPage = lastPage
        };
    }

    /// <inheritdoc />
    public async Task<OrderBuyResponseDto> CreateInfiniteMibaoOrderAsync(int userId, InfiniteMibaoOrderBuyRequest request)
    {
        // 1. 获取用户信息
        var user = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.Mobile, u.MbNumber })
            .FirstOrDefaultAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        if (string.IsNullOrEmpty(user.Mobile))
        {
            throw new InvalidOperationException("请先绑定手机号");
        }

        // 2. 获取商品信息
        var goods = await _dbContext.Goods
            .Where(g => g.Id == request.GoodsId && g.DeletedAt == null)
            .Select(g => new
            {
                g.Id,
                g.Title,
                g.ImgUrlDetail,
                g.Type,
                g.Price,
                g.Status,
                g.ChoujiangXianzhi,
                g.DailyXiangou
            })
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new InvalidOperationException("盒子不存在");
        }

        if (goods.Status != 1)
        {
            throw new InvalidOperationException("盒子已下架");
        }

        // 3. 验证商品类型（连击赏类型：9）
        if (goods.Type != 9)
        {
            throw new InvalidOperationException("非法请求");
        }

        // 4. 验证抽奖门槛
        if (goods.ChoujiangXianzhi > 0)
        {
            var userPrice = await _dbContext.Orders
                .Where(o => o.Status == 1 && o.UserId == userId)
                .SumAsync(o => o.Price);
            var userUseMoney = await _dbContext.Orders
                .Where(o => o.Status == 1 && o.UserId == userId)
                .SumAsync(o => o.UseMoney);

            var totalSpent = userPrice + userUseMoney;
            if (totalSpent < goods.ChoujiangXianzhi)
            {
                throw new InvalidOperationException($"消费满{goods.ChoujiangXianzhi}元可参与 已消费{Math.Round(totalSpent, 2)}元");
            }
        }

        // 5. 验证每日限购
        if (goods.DailyXiangou > 0)
        {
            var todayStart = DateTime.Today;
            var todayStartTimestamp = new DateTimeOffset(todayStart).ToUnixTimeSeconds();
            var todayEndTimestamp = new DateTimeOffset(todayStart.AddDays(1)).ToUnixTimeSeconds();

            var todayBuyCount = await _dbContext.Orders
                .Where(o => o.UserId == userId
                    && o.GoodsId == request.GoodsId
                    && o.Status == 1
                    && o.Addtime >= todayStartTimestamp
                    && o.Addtime < todayEndTimestamp)
                .CountAsync();

            if (todayBuyCount >= goods.DailyXiangou)
            {
                throw new InvalidOperationException($"该商品每日限购{goods.DailyXiangou}次，今日已购买{todayBuyCount}次");
            }
        }

        // 6. 验证抽奖次数
        if (request.PrizeNum > 20)
        {
            throw new InvalidOperationException("一次最多购买20次");
        }

        // 7. 验证秘宝池抽奖次数
        var userMbNumber = user.MbNumber ?? 0;
        if (request.PrizeNum > userMbNumber)
        {
            throw new InvalidOperationException("秘宝池抽奖次数不足");
        }

        // 8. 生成订单号
        var orderNum = $"MH_LJS{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";
        var currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var orderTotal = goods.Price * request.PrizeNum;

        // 9. 创建订单
        using var transaction = await _dbContext.Database.BeginTransactionAsync();
        try
        {
            var order = new Order
            {
                UserId = userId,
                OrderNum = orderNum,
                OrderTotal = orderTotal,
                OrderZheTotal = 0,
                Price = 0,
                UseMoney = 0,
                UseIntegral = 0,
                UseMoney2 = 0,
                UseScore = 0,
                Zhe = 0,
                GoodsId = request.GoodsId,
                Num = 0,
                GoodsPrice = goods.Price,
                GoodsTitle = goods.Title,
                GoodsImgurl = goods.ImgUrlDetail,
                PrizeNum = request.PrizeNum,
                Status = 0,
                PayType = 1,
                OrderType = goods.Type,
                Addtime = (int)currentTimestamp,
                CouponId = null,
                UseCoupon = 0,
                IsMibao = (byte)request.IsMibao,
                IsShouZhe = 0,
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now
            };

            _dbContext.Orders.Add(order);
            await _dbContext.SaveChangesAsync();

            // 10. 扣减用户秘宝池次数
            var userEntity = await _dbContext.Users.FindAsync(userId);
            if (userEntity != null)
            {
                userEntity.MbNumber = (userEntity.MbNumber ?? 0) - request.PrizeNum;
                userEntity.UpdatedAt = DateTime.Now;
            }

            // 11. 标记订单为已支付（秘宝池使用次数支付）
            order.Status = 1;
            order.PayTime = (int)currentTimestamp;

            await _dbContext.SaveChangesAsync();
            await transaction.CommitAsync();

            return new OrderBuyResponseDto
            {
                Status = 0,
                OrderNum = orderNum,
                Res = null
            };
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "创建连击赏秘宝订单失败: UserId={UserId}, GoodsId={GoodsId}", userId, request.GoodsId);
            throw new InvalidOperationException("购买失败,请刷新重试");
        }
    }

    /// <inheritdoc />
    public async Task<string> GetUserTestTokenAsync(int userId, int targetUserId)
    {
        // 1. 验证当前用户是否为测试账号
        var currentUser = await _dbContext.Users
            .Where(u => u.Id == userId)
            .Select(u => new { u.Id, u.IsTest })
            .FirstOrDefaultAsync();

        if (currentUser == null || currentUser.IsTest != 2)
        {
            return string.Empty;
        }

        // 2. 查找目标用户
        var targetUser = await _dbContext.Users
            .Where(u => u.Id == targetUserId || u.Uid == targetUserId.ToString())
            .Select(u => new { u.Id })
            .FirstOrDefaultAsync();

        if (targetUser == null)
        {
            return string.Empty;
        }

        // 3. 获取目标用户的账号Token
        var userAccount = await _dbContext.UserAccounts
            .Where(ua => ua.UserId == targetUser.Id)
            .Select(ua => ua.AccountToken)
            .FirstOrDefaultAsync();

        return userAccount ?? string.Empty;
    }

    #endregion
}
