using HoneyBox.Admin.Business.Models;
using HoneyBox.Admin.Business.Models.Goods;
using HoneyBox.Admin.Business.Services.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Admin.Business.Services;

/// <summary>
/// 商品管理服务实现
/// </summary>
public class GoodsService : IGoodsService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly ILogger<GoodsService> _logger;

    // 盒子类型名称映射
    private static readonly Dictionary<int, string> BoxTypeNames = new()
    {
        { 1, "一番赏" },
        { 2, "无限赏" },
        { 3, "擂台赏" },
        { 4, "抽卡机" },
        { 5, "福袋" },
        { 6, "幸运赏" },
        { 8, "盲盒" },
        { 9, "扭蛋" },
        { 10, "积分商城" },
        { 11, "转转赏" },
        { 12, "连击赏" },
        { 15, "福利屋" },
        { 16, "连抽赏" },
        { 17, "大乱斗" }
    };

    public GoodsService(
        HoneyBoxDbContext dbContext,
        ILogger<GoodsService> logger)
    {
        _dbContext = dbContext;
        _logger = logger;
    }

    #region 商品管理

    // 使用模板奖品的类型（无限赏类型）：库存直接使用 goods 表的 stock/sale_stock
    // 其他类型（箱号类型）：库存需要从 goods_items 表汇总计算
    private static readonly int[] TemplateTypes = { 2, 8, 9, 15, 16, 17 };

    /// <inheritdoc />
    public async Task<PagedResult<GoodsListResponse>> GetGoodsListAsync(GoodsListRequest request)
    {
        var query = _dbContext.Goods
            .AsNoTracking()
            .Where(g => g.DeletedAt == null);

        // 应用过滤条件
        query = ApplyGoodsFilters(query, request);

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

        // 获取商品列表
        var goods = await query
            .OrderByDescending(g => g.Sort)
            .ThenByDescending(g => g.CreatedAt)  // Sort 相同时，按创建时间降序（新的在前）
            .ThenByDescending(g => g.Id)
            .Skip(request.Skip)
            .Take(request.PageSize)
            .ToListAsync();

        // 获取非无限赏类型商品的ID列表，用于计算实际库存
        var nonTemplateGoodsIds = goods
            .Where(g => !TemplateTypes.Contains(g.Type))
            .Select(g => g.Id)
            .ToList();

        // 批量查询非无限赏商品的奖品库存汇总
        var stockSummary = new Dictionary<int, (int TotalStock, int SurplusStock)>();
        if (nonTemplateGoodsIds.Any())
        {
            var summary = await _dbContext.GoodsItems
                .AsNoTracking()
                .Where(gi => nonTemplateGoodsIds.Contains(gi.GoodsId) && gi.GoodsListId == 0) // 只统计父奖品
                .GroupBy(gi => gi.GoodsId)
                .Select(g => new
                {
                    GoodsId = g.Key,
                    TotalStock = g.Sum(x => x.Stock),
                    SurplusStock = g.Sum(x => x.SurplusStock)
                })
                .ToListAsync();

            foreach (var s in summary)
            {
                stockSummary[s.GoodsId] = (s.TotalStock, s.SurplusStock);
            }
        }

        // 映射结果，传入库存汇总数据
        var list = goods.Select(g => MapToGoodsListResponse(g, stockSummary)).ToList();

        return PagedResult<GoodsListResponse>.Create(list, total, request.Page, request.PageSize);
    }

    /// <inheritdoc />
    public async Task<GoodsDetailResponse?> GetGoodsDetailAsync(int goodsId)
    {
        var goods = await _dbContext.Goods
            .AsNoTracking()
            .FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);

        if (goods == null)
        {
            return null;
        }

        return MapToGoodsDetailResponse(goods);
    }

    /// <inheritdoc />
    public async Task<int> CreateGoodsAsync(GoodsCreateRequest request, int operatorId)
    {
        // 验证商品类型
        if (!BoxTypeNames.ContainsKey(request.Type))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "无效的商品类型");
        }

        var now = DateTime.Now;
        var goods = new Good
        {
            Title = request.Title,
            Price = request.Price,
            Type = (byte)request.Type,
            ImgUrl = request.ImgUrl,
            ImgUrlBanner = request.ImgUrlBanner,
            ImgUrlDetail = request.ImgUrlDetail,
            Stock = request.Stock,
            SaleStock = 0,
            Sort = request.Sort,
            DailyXiangou = request.DailyLimit,
            LockIs = (byte)request.LockIs,
            IntegralIs = (byte)request.IntegralIs,
            ShowIs = (byte)request.ShowIs,
            CouponIs = (byte)request.CouponIs,
            CouponPro = request.CouponPro,
            FlwStartTime = request.FlwStartTime,
            FlwEndTime = request.FlwEndTime,
            OpenTime = request.OpenTime,
            ChoujiangXianzhi = request.ChoujiangXianzhi ?? 0,
            CategoryId = request.CategoryId,
            GoodsDescribe = request.GoodsDescribe,
            NewIs = (byte)request.NewIs,
            IsShouZhe = (byte)request.IsShouZhe,
            RageIs = (byte)request.RageIs,
            Rage = request.Rage,
            LingzhuIs = (byte)request.LingzhuIs,
            LingzhuFan = request.LingzhuFan,
            IsAutoXiajia = (byte)request.IsAutoXiajia,
            XiajiaLirun = (int)request.XiajiaLirun,
            XiajiaAutoCoushu = (int)request.XiajiaAutoCoushu,
            XiajiaJine = (int)request.XiajiaJine,
            UnlockAmount = request.UnlockAmount,
            Status = 0, // 默认下架
            PrizeNum = 0,
            IsFlw = (byte)(request.Type == 15 ? 1 : 0),
            CreatedAt = now,
            UpdatedAt = now
        };

        _dbContext.Goods.Add(goods);
        await _dbContext.SaveChangesAsync();

        // 记录操作日志
        await LogGoodsOperationAsync(goods.Id, "create", $"创建商品: {goods.Title}", operatorId);

        _logger.LogInformation("创建商品成功: GoodsId={GoodsId}, Title={Title}, Operator={Operator}",
            goods.Id, goods.Title, operatorId);

        return goods.Id;
    }


    /// <inheritdoc />
    public async Task<bool> UpdateGoodsAsync(int goodsId, GoodsUpdateRequest request, int operatorId)
    {
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (goods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "商品不存在");
        }

        // 验证商品类型
        if (!BoxTypeNames.ContainsKey(request.Type))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "无效的商品类型");
        }

        // 防止库存减少
        if (request.Stock < goods.Stock)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "不允许减少库存");
        }

        // 检查是否需要复制奖品配置（库存增加时）
        var stockIncrease = request.Stock - goods.Stock;
        if (stockIncrease > 0)
        {
            await CopyPrizeConfigurationsAsync(goodsId, stockIncrease);
        }

        // 更新商品信息
        goods.Title = request.Title;
        goods.Price = request.Price;
        goods.Type = (byte)request.Type;
        goods.ImgUrl = request.ImgUrl;
        goods.ImgUrlBanner = request.ImgUrlBanner;
        goods.ImgUrlDetail = request.ImgUrlDetail;
        goods.Stock = request.Stock;
        goods.Sort = request.Sort;
        goods.DailyXiangou = request.DailyLimit;
        goods.LockIs = (byte)request.LockIs;
        goods.IntegralIs = (byte)request.IntegralIs;
        goods.ShowIs = (byte)request.ShowIs;
        goods.CouponIs = (byte)request.CouponIs;
        goods.CouponPro = request.CouponPro;
        goods.FlwStartTime = request.FlwStartTime;
        goods.FlwEndTime = request.FlwEndTime;
        goods.OpenTime = request.OpenTime;
        goods.ChoujiangXianzhi = request.ChoujiangXianzhi ?? 0;
        goods.CategoryId = request.CategoryId;
        goods.GoodsDescribe = request.GoodsDescribe;
        goods.NewIs = (byte)request.NewIs;
        goods.IsShouZhe = (byte)request.IsShouZhe;
        goods.RageIs = (byte)request.RageIs;
        goods.Rage = request.Rage;
        goods.LingzhuIs = (byte)request.LingzhuIs;
        goods.LingzhuFan = request.LingzhuFan;
        goods.IsAutoXiajia = (byte)request.IsAutoXiajia;
        goods.XiajiaLirun = (int)request.XiajiaLirun;
        goods.XiajiaAutoCoushu = (int)request.XiajiaAutoCoushu;
        goods.XiajiaJine = (int)request.XiajiaJine;
        goods.UnlockAmount = request.UnlockAmount;
        goods.IsFlw = (byte)(request.Type == 15 ? 1 : 0);
        goods.UpdatedAt = DateTime.Now;

        var result = await _dbContext.SaveChangesAsync() > 0;

        // 记录操作日志
        await LogGoodsOperationAsync(goodsId, "update", $"更新商品: {goods.Title}", operatorId);

        _logger.LogInformation("更新商品成功: GoodsId={GoodsId}, Operator={Operator}", goodsId, operatorId);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> DeleteGoodsAsync(int goodsId, int operatorId)
    {
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (goods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "商品不存在");
        }

        // 软删除
        goods.DeletedAt = DateTime.Now;
        goods.UpdatedAt = DateTime.Now;

        var result = await _dbContext.SaveChangesAsync() > 0;

        // 记录操作日志
        await LogGoodsOperationAsync(goodsId, "delete", $"删除商品: {goods.Title}", operatorId);

        _logger.LogInformation("删除商品成功: GoodsId={GoodsId}, Operator={Operator}", goodsId, operatorId);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> SetGoodsStatusAsync(int goodsId, int status, int operatorId)
    {
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (goods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "商品不存在");
        }

        var oldStatus = goods.Status;
        goods.Status = (byte)status;
        goods.UpdatedAt = DateTime.Now;

        var result = await _dbContext.SaveChangesAsync() > 0;

        // 记录操作日志
        var operation = status == 1 ? "上架" : "下架";
        await LogGoodsOperationAsync(goodsId, "status", $"商品{operation}: {goods.Title}", operatorId);

        _logger.LogInformation("商品状态变更: GoodsId={GoodsId}, OldStatus={OldStatus}, NewStatus={NewStatus}, Operator={Operator}",
            goodsId, oldStatus, status, operatorId);

        return result;
    }

    #endregion

    #region 奖品管理

    /// <summary>
    /// 创建奖品奖励配置
    /// 在 rewards 表中创建对应的奖励记录
    /// </summary>
    /// <param name="prizeCode">奖品编码，用作 reward_id</param>
    /// <param name="rewards">奖励配置列表</param>
    /// <param name="now">当前时间</param>
    /// <returns>生成的 reward_id</returns>
    private async Task<string> CreatePrizeRewardsAsync(string prizeCode, List<PrizeRewardItem> rewards, DateTime now)
    {
        // 使用 prize_code 作为 reward_id，确保唯一性
        var rewardId = $"PRIZE_{prizeCode}";

        // 删除已存在的同 reward_id 的记录（如果有）
        var existingRewards = await _dbContext.Rewards
            .Where(r => r.RewardId == rewardId)
            .ToListAsync();
        if (existingRewards.Any())
        {
            _dbContext.Rewards.RemoveRange(existingRewards);
        }

        // 创建新的奖励记录
        foreach (var item in rewards.Where(r => r.Amount > 0))
        {
            var reward = new HoneyBox.Model.Entities.Reward
            {
                RewardId = rewardId,
                RewardType = item.Type,
                RewardValue = item.Amount,
                RewardExtend = null,
                CreatedAt = now,
                UpdatedAt = now
            };
            _dbContext.Rewards.Add(reward);
        }

        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("创建奖品奖励配置: RewardId={RewardId}, Count={Count}", 
            rewardId, rewards.Count(r => r.Amount > 0));

        return rewardId;
    }

    /// <inheritdoc />
    public async Task<List<PrizeDto>> GetPrizesAsync(int goodsId)
    {
        // 验证商品存在
        var goodsExists = await _dbContext.Goods.AnyAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (!goodsExists)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "商品不存在");
        }

        var prizes = await _dbContext.GoodsItems
            .AsNoTracking()
            .Where(gi => gi.GoodsId == goodsId)
            .OrderBy(gi => gi.Sort)
            .ThenBy(gi => gi.Num)
            .ToListAsync();

        // 获取所有奖品等级ID
        var shangIds = prizes
            .Where(p => p.ShangId.HasValue)
            .Select(p => p.ShangId!.Value)
            .Distinct()
            .ToList();

        // 批量查询等级信息
        var prizeLevels = await _dbContext.PrizeLevels
            .AsNoTracking()
            .Where(pl => shangIds.Contains(pl.Id))
            .ToDictionaryAsync(pl => pl.Id, pl => new PrizeLevelInfo { Title = pl.Title, Color = pl.Color });

        // 获取所有奖励ID
        var rewardIds = prizes
            .Where(p => !string.IsNullOrEmpty(p.RewardId))
            .Select(p => p.RewardId!)
            .Distinct()
            .ToList();

        // 批量查询奖励配置
        var rewardsDict = new Dictionary<string, List<PrizeRewardItem>>();
        if (rewardIds.Any())
        {
            var rewards = await _dbContext.Rewards
                .AsNoTracking()
                .Where(r => rewardIds.Contains(r.RewardId))
                .ToListAsync();

            rewardsDict = rewards
                .GroupBy(r => r.RewardId)
                .ToDictionary(
                    g => g.Key,
                    g => g.Select(r => new PrizeRewardItem { Type = r.RewardType, Amount = (int)r.RewardValue }).ToList()
                );
        }

        return prizes.Select(p => MapToPrizeDto(p, prizeLevels, rewardsDict)).ToList();
    }

    /// <summary>
    /// 奖品等级信息
    /// </summary>
    private class PrizeLevelInfo
    {
        public string Title { get; set; } = string.Empty;
        public string? Color { get; set; }
    }

    /// <inheritdoc />
    public async Task<int> AddPrizeAsync(int goodsId, PrizeCreateRequest request)
    {
        // 验证商品存在
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (goods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "商品不存在");
        }

        var now = DateTime.Now;
        var prizeCode = GeneratePrizeCode();
        
        // 处理奖励配置：如果有 rewards 配置，创建 rewards 表记录
        var rewardId = request.RewardId;
        if (request.Rewards != null && request.Rewards.Count > 0)
        {
            rewardId = await CreatePrizeRewardsAsync(prizeCode, request.Rewards, now);
        }
        
        // 根据商品类型决定添加逻辑
        // 无限赏(2)、盲盒(8)、扭蛋(9)、福利屋(15)、连抽赏(16)、大乱斗(17)：num = 0（模板奖品，只添加一条）
        // 一番赏(1)、擂台赏(3)、福袋(5)、幸运赏(6)、积分商城(10)、转转赏(11)：为每个箱子都添加一条奖品
        var templateTypes = new[] { 2, 8, 9, 15, 16, 17 }; // 使用模板奖品的类型
        
        // 处理宝箱子奖品的情况
        if (request.GoodsListId > 0)
        {
            return await AddChildPrizeAsync(goodsId, request, now, rewardId);
        }
        
        if (templateTypes.Contains(goods.Type))
        {
            // 模板类型：只添加一条 num=0 的记录
            var prize = new GoodsItem
            {
                GoodsId = goodsId,
                Num = 0,
                Title = request.Title,
                ImgUrl = request.ImgUrl,
                ImgUrlDetail = request.ImgUrlDetail,
                Stock = request.Stock,
                SurplusStock = request.Stock,
                Price = request.Price,
                Money = request.Money,
                ScMoney = request.ScMoney,
                RealPro = request.RealPro,
                GoodsType = (byte)request.GoodsType,
                Sort = request.Sort,
                ShangId = request.ShangId,
                RewardNum = request.RewardNum,
                Rank = request.Rank,
                GiveMoney = request.GiveMoney,
                CardNo = request.CardNo,
                PrizeCode = prizeCode,
                Type = (byte)request.Type,
                LianJiType = (byte)request.LianJiType,
                RewardId = rewardId,
                Doubling = request.Doubling,
                IsLingzhu = (byte)request.IsLingzhu,
                PrizeNum = 1,
                GoodsListId = 0,
                CreatedAt = now,
                UpdatedAt = now
            };

            _dbContext.GoodsItems.Add(prize);
            await _dbContext.SaveChangesAsync();

            // 更新商品奖品数量
            goods.PrizeNum = await _dbContext.GoodsItems.CountAsync(gi => gi.GoodsId == goodsId && gi.Num == 0);
            goods.UpdatedAt = now;
            await _dbContext.SaveChangesAsync();

            _logger.LogInformation("添加模板奖品成功: GoodsId={GoodsId}, PrizeId={PrizeId}, Title={Title}",
                goodsId, prize.Id, prize.Title);

            return prize.Id;
        }
        else
        {
            // 箱号类型（一番赏等）：为每个箱子都添加一条奖品
            var boxCount = goods.Stock; // 箱数
            if (boxCount <= 0)
            {
                throw new BusinessException(BusinessErrorCodes.ValidationFailed, "商品箱数必须大于0才能添加奖品");
            }

            var prizes = new List<GoodsItem>();
            for (int i = 1; i <= boxCount; i++)
            {
                var prize = new GoodsItem
                {
                    GoodsId = goodsId,
                    Num = i, // 箱号
                    Title = request.Title,
                    ImgUrl = request.ImgUrl,
                    ImgUrlDetail = request.ImgUrlDetail,
                    Stock = request.Stock,
                    SurplusStock = request.Stock,
                    Price = request.Price,
                    Money = request.Money,
                    ScMoney = request.ScMoney,
                    RealPro = request.RealPro,
                    GoodsType = (byte)request.GoodsType,
                    Sort = request.Sort,
                    ShangId = request.ShangId,
                    RewardNum = request.RewardNum,
                    Rank = request.Rank,
                    GiveMoney = request.GiveMoney,
                    CardNo = request.CardNo,
                    PrizeCode = prizeCode, // 同一个 prize_code，表示是同一个奖品配置
                    Type = (byte)request.Type,
                    LianJiType = (byte)request.LianJiType,
                    RewardId = rewardId,
                    Doubling = request.Doubling,
                    IsLingzhu = (byte)request.IsLingzhu,
                    PrizeNum = 1,
                    GoodsListId = 0,
                    CreatedAt = now,
                    UpdatedAt = now
                };
                prizes.Add(prize);
            }

            _dbContext.GoodsItems.AddRange(prizes);
            await _dbContext.SaveChangesAsync();

            // 更新商品奖品数量（按第一箱的奖品数计算）
            goods.PrizeNum = await _dbContext.GoodsItems.CountAsync(gi => gi.GoodsId == goodsId && gi.Num == 1);
            
            // 商城赏(type=10)：同步 goods.stock/sale_stock 与 goods_items 汇总值
            // 商城赏的库存模型是多批次进货，每批一条 goods_items，需要保持 goods 表的汇总值同步
            if (goods.Type == 10)
            {
                var stockSummary = await _dbContext.GoodsItems
                    .Where(gi => gi.GoodsId == goodsId)
                    .GroupBy(gi => 1)
                    .Select(g => new
                    {
                        TotalStock = g.Sum(x => x.Stock),
                        TotalSold = g.Sum(x => x.Stock) - g.Sum(x => x.SurplusStock)
                    })
                    .FirstOrDefaultAsync();

                if (stockSummary != null)
                {
                    goods.Stock = stockSummary.TotalStock;
                    goods.SaleStock = stockSummary.TotalSold;
                }
            }
            
            goods.UpdatedAt = now;
            await _dbContext.SaveChangesAsync();

            _logger.LogInformation("添加箱号奖品成功: GoodsId={GoodsId}, BoxCount={BoxCount}, Title={Title}, PrizeCode={PrizeCode}",
                goodsId, boxCount, request.Title, prizeCode);

            return prizes.First().Id;
        }
    }

    /// <summary>
    /// 添加宝箱子奖品
    /// 当父奖品存在于多个箱号中时，会为每个箱号的父奖品都创建对应的子奖品
    /// </summary>
    private async Task<int> AddChildPrizeAsync(int goodsId, PrizeCreateRequest request, DateTime now, string? rewardId = null)
    {
        // 获取父奖品信息
        var parentPrize = await _dbContext.GoodsItems
            .AsNoTracking()
            .FirstOrDefaultAsync(gi => gi.Id == request.GoodsListId && gi.GoodsId == goodsId);

        if (parentPrize == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "宝箱父奖品不存在");
        }

        // 验证父奖品是宝箱类型 (goods_type = 4)
        if (parentPrize.GoodsType != 4)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "只有宝箱类型的奖品才能添加子奖品");
        }

        // 子奖品生成自己的 prize_code
        var childPrizeCode = GeneratePrizeCode();
        
        // 如果有 rewards 配置但没有传入 rewardId，创建 rewards 表记录
        if (string.IsNullOrEmpty(rewardId) && request.Rewards != null && request.Rewards.Count > 0)
        {
            rewardId = await CreatePrizeRewardsAsync(childPrizeCode, request.Rewards, now);
        }

        // 查找所有箱号中具有相同 prize_code 的父奖品（同一个宝箱配置在不同箱号中的记录）
        var sameParentPrizes = await _dbContext.GoodsItems
            .AsNoTracking()
            .Where(gi => gi.GoodsId == goodsId 
                      && gi.PrizeCode == parentPrize.PrizeCode 
                      && gi.GoodsListId == 0) // 确保只查询父奖品
            .ToListAsync();

        var childPrizes = new List<GoodsItem>();

        foreach (var parent in sameParentPrizes)
        {
            var childPrize = new GoodsItem
            {
                GoodsId = goodsId,
                Num = parent.Num, // 继承父奖品的箱号
                Title = request.Title,
                ImgUrl = request.ImgUrl,
                ImgUrlDetail = request.ImgUrlDetail,
                Stock = request.Stock,
                SurplusStock = request.Stock,
                Price = request.Price,
                Money = request.Money,
                ScMoney = request.ScMoney,
                RealPro = request.RealPro,
                GoodsType = (byte)request.GoodsType,
                Sort = request.Sort,
                ShangId = request.ShangId,
                RewardNum = request.RewardNum,
                Rank = request.Rank,
                GiveMoney = request.GiveMoney,
                CardNo = request.CardNo,
                PrizeCode = childPrizeCode, // 子奖品使用自己的 prize_code
                Type = (byte)request.Type,
                LianJiType = (byte)request.LianJiType,
                RewardId = rewardId,
                Doubling = request.Doubling,
                IsLingzhu = (byte)request.IsLingzhu,
                PrizeNum = 1,
                GoodsListId = parent.Id, // 关联到对应箱号的父奖品
                CreatedAt = now,
                UpdatedAt = now
            };
            childPrizes.Add(childPrize);
        }

        _dbContext.GoodsItems.AddRange(childPrizes);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("添加宝箱子奖品成功: GoodsId={GoodsId}, ParentPrizeCode={ParentPrizeCode}, ChildCount={ChildCount}, Title={Title}",
            goodsId, parentPrize.PrizeCode, childPrizes.Count, request.Title);

        return childPrizes.First().Id;
    }


    /// <inheritdoc />
    public async Task<bool> UpdatePrizeAsync(int prizeId, PrizeUpdateRequest request)
    {
        var prize = await _dbContext.GoodsItems.FirstOrDefaultAsync(gi => gi.Id == prizeId);
        if (prize == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "奖品不存在");
        }

        var now = DateTime.Now;
        
        // 处理奖励配置：如果有 rewards 配置，创建/更新 rewards 表记录
        var rewardId = request.RewardId;
        if (request.Rewards != null && request.Rewards.Count > 0)
        {
            // 使用现有的 prize_code 或生成新的
            var prizeCode = prize.PrizeCode ?? GeneratePrizeCode();
            rewardId = await CreatePrizeRewardsAsync(prizeCode, request.Rewards, now);
        }

        prize.Title = request.Title;
        prize.ImgUrl = request.ImgUrl;
        prize.ImgUrlDetail = request.ImgUrlDetail;
        prize.Stock = request.Stock;
        prize.SurplusStock = request.Stock; // 更新剩余库存
        prize.Price = request.Price;
        prize.Money = request.Money;
        prize.ScMoney = request.ScMoney;
        prize.RealPro = request.RealPro;
        prize.GoodsType = (byte)request.GoodsType;
        prize.Sort = request.Sort;
        prize.ShangId = request.ShangId;
        prize.RewardNum = request.RewardNum;
        prize.Rank = request.Rank;
        prize.GiveMoney = request.GiveMoney;
        prize.CardNo = request.CardNo;
        prize.Type = (byte)request.Type;
        prize.LianJiType = (byte)request.LianJiType;
        prize.RewardId = rewardId;
        prize.Doubling = request.Doubling;
        prize.IsLingzhu = (byte)request.IsLingzhu;
        prize.UpdatedAt = now;

        // 商城赏(type=10)：同步 goods.stock/sale_stock
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == prize.GoodsId);
        if (goods != null && goods.Type == 10)
        {
            var stockSummary = await _dbContext.GoodsItems
                .Where(gi => gi.GoodsId == prize.GoodsId)
                .GroupBy(gi => 1)
                .Select(g => new
                {
                    TotalStock = g.Sum(x => x.Stock),
                    TotalSold = g.Sum(x => x.Stock) - g.Sum(x => x.SurplusStock)
                })
                .FirstOrDefaultAsync();

            if (stockSummary != null)
            {
                goods.Stock = stockSummary.TotalStock;
                goods.SaleStock = stockSummary.TotalSold;
                goods.UpdatedAt = now;
            }
        }

        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("更新奖品成功: PrizeId={PrizeId}, Title={Title}", prizeId, prize.Title);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> DeletePrizeAsync(int prizeId)
    {
        var prize = await _dbContext.GoodsItems.FirstOrDefaultAsync(gi => gi.Id == prizeId);
        if (prize == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "奖品不存在");
        }

        var goodsId = prize.GoodsId;

        _dbContext.GoodsItems.Remove(prize);

        // 更新商品奖品数量
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == goodsId);
        if (goods != null)
        {
            goods.PrizeNum = await _dbContext.GoodsItems.CountAsync(gi => gi.GoodsId == goodsId) - 1;
            
            // 商城赏(type=10)：同步 goods.stock/sale_stock
            if (goods.Type == 10)
            {
                var stockSummary = await _dbContext.GoodsItems
                    .Where(gi => gi.GoodsId == goodsId && gi.Id != prizeId)
                    .GroupBy(gi => 1)
                    .Select(g => new
                    {
                        TotalStock = g.Sum(x => x.Stock),
                        TotalSold = g.Sum(x => x.Stock) - g.Sum(x => x.SurplusStock)
                    })
                    .FirstOrDefaultAsync();

                goods.Stock = stockSummary?.TotalStock ?? 0;
                goods.SaleStock = stockSummary?.TotalSold ?? 0;
            }
            
            goods.UpdatedAt = DateTime.Now;
        }

        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("删除奖品成功: PrizeId={PrizeId}, GoodsId={GoodsId}", prizeId, goodsId);

        return result;
    }

    #endregion

    #region 盒子类型管理

    /// <inheritdoc />
    public async Task<List<GoodsTypeDto>> GetGoodsTypesAsync()
    {
        var types = await _dbContext.GoodsTypes
            .AsNoTracking()
            .OrderBy(t => t.SortOrder)
            .ToListAsync();

        return types.Select(t => new GoodsTypeDto
        {
            Id = t.Id,
            Name = t.Name,
            Value = t.Value,
            SortOrder = t.SortOrder,
            IsShow = t.IsShow,
            IsFenlei = t.IsFenlei,
            FlName = t.FlName,
            CornerText = t.CornerText,
            PayWechat = t.PayWechat,
            PayBalance = t.PayBalance,
            PayCurrency = t.PayCurrency,
            PayCurrency2 = t.PayCurrency2,
            PayCoupon = t.PayCoupon,
            IsDeduction = t.IsDeduction,
            Remark = t.Remark
        }).ToList();
    }

    /// <inheritdoc />
    public async Task<int> CreateGoodsTypeAsync(GoodsTypeCreateRequest request)
    {
        // 验证类型名称
        if (string.IsNullOrWhiteSpace(request.Name))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "类型名称不能为空");
        }

        // 检查类型值是否已存在
        var exists = await _dbContext.GoodsTypes.AnyAsync(t => t.Value == request.Value);
        if (exists)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "类型Key已存在，请更换");
        }

        // 验证分类显示设置
        if (request.IsFenlei == 1 && string.IsNullOrWhiteSpace(request.FlName))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "选择分类显示时，必须填写分类名称");
        }

        var goodsType = new GoodsType
        {
            Name = request.Name,
            Value = request.Value,
            SortOrder = request.SortOrder,
            IsShow = (byte)request.IsShow,
            IsFenlei = (byte)request.IsFenlei,
            FlName = request.FlName ?? string.Empty,
            CornerText = request.CornerText,
            PayWechat = (byte)request.PayWechat,
            PayBalance = (byte)request.PayBalance,
            PayCurrency = (byte)request.PayCurrency,
            PayCurrency2 = (byte)request.PayCurrency2,
            PayCoupon = (byte)request.PayCoupon,
            IsDeduction = (byte)request.IsDeduction,
            Remark = request.Remark
        };

        _dbContext.GoodsTypes.Add(goodsType);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("创建盒子类型成功: TypeId={TypeId}, Name={Name}", goodsType.Id, goodsType.Name);

        return goodsType.Id;
    }

    /// <inheritdoc />
    public async Task<bool> UpdateGoodsTypeAsync(int typeId, GoodsTypeUpdateRequest request)
    {
        var goodsType = await _dbContext.GoodsTypes.FirstOrDefaultAsync(t => t.Id == typeId);
        if (goodsType == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子类型不存在");
        }

        // 验证类型名称
        if (string.IsNullOrWhiteSpace(request.Name))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "类型名称不能为空");
        }

        // 检查类型值是否已存在（排除自身）
        var exists = await _dbContext.GoodsTypes.AnyAsync(t => t.Value == request.Value && t.Id != typeId);
        if (exists)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "类型Key已存在，请更换");
        }

        // 验证分类显示设置
        if (request.IsFenlei == 1 && string.IsNullOrWhiteSpace(request.FlName))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "选择分类显示时，必须填写分类名称");
        }

        goodsType.Name = request.Name;
        goodsType.Value = request.Value;
        goodsType.SortOrder = request.SortOrder;
        goodsType.IsShow = (byte)request.IsShow;
        goodsType.IsFenlei = (byte)request.IsFenlei;
        goodsType.FlName = request.FlName ?? string.Empty;
        goodsType.CornerText = request.CornerText;
        goodsType.PayWechat = (byte)request.PayWechat;
        goodsType.PayBalance = (byte)request.PayBalance;
        goodsType.PayCurrency = (byte)request.PayCurrency;
        goodsType.PayCurrency2 = (byte)request.PayCurrency2;
        goodsType.PayCoupon = (byte)request.PayCoupon;
        goodsType.IsDeduction = (byte)request.IsDeduction;
        goodsType.Remark = request.Remark;

        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("更新盒子类型成功: TypeId={TypeId}, Name={Name}", typeId, goodsType.Name);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> DeleteGoodsTypeAsync(int typeId)
    {
        var goodsType = await _dbContext.GoodsTypes.FirstOrDefaultAsync(t => t.Id == typeId);
        if (goodsType == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子类型不存在");
        }

        // 检查是否有商品使用此类型
        var hasGoods = await _dbContext.Goods.AnyAsync(g => g.Type == goodsType.Value && g.DeletedAt == null);
        if (hasGoods)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "该类型下存在商品，无法删除");
        }

        _dbContext.GoodsTypes.Remove(goodsType);
        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("删除盒子类型成功: TypeId={TypeId}, Name={Name}", typeId, goodsType.Name);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> SetGoodsTypeStatusAsync(int typeId, GoodsTypeStatusRequest request)
    {
        var goodsType = await _dbContext.GoodsTypes.FirstOrDefaultAsync(t => t.Id == typeId);
        if (goodsType == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子类型不存在");
        }

        // 根据类型更新对应字段
        switch (request.Type.ToLower())
        {
            case "is_show":
                goodsType.IsShow = (byte)request.Value;
                break;
            case "is_fenlei":
                goodsType.IsFenlei = (byte)request.Value;
                break;
            default:
                throw new BusinessException(BusinessErrorCodes.ValidationFailed, "无效的状态类型");
        }

        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("更新盒子类型状态成功: TypeId={TypeId}, Type={Type}, Value={Value}",
            typeId, request.Type, request.Value);

        return result;
    }

    #endregion

    #region Private Helper Methods

    /// <summary>
    /// 应用商品过滤条件
    /// </summary>
    private IQueryable<Good> ApplyGoodsFilters(IQueryable<Good> query, GoodsListRequest request)
    {
        if (!string.IsNullOrWhiteSpace(request.Title))
        {
            query = query.Where(g => g.Title.Contains(request.Title));
        }

        if (request.Status.HasValue)
        {
            query = query.Where(g => g.Status == request.Status.Value);
        }

        // 只有当 Type 有值且大于0时才过滤（0表示"全部"）
        if (request.Type.HasValue && request.Type.Value > 0)
        {
            query = query.Where(g => g.Type == request.Type.Value);
        }

        return query;
    }

    /// <summary>
    /// 映射商品到列表响应
    /// </summary>
    /// <param name="goods">商品实体</param>
    /// <param name="stockSummary">非无限赏商品的库存汇总（可选）</param>
    private GoodsListResponse MapToGoodsListResponse(Good goods, Dictionary<int, (int TotalStock, int SurplusStock)>? stockSummary = null)
    {
        int stock, saleStock;

        // 判断是否为无限赏类型（使用模板奖品的类型）
        if (TemplateTypes.Contains(goods.Type))
        {
            // 无限赏类型：直接使用 goods 表的库存字段
            stock = goods.Stock;
            saleStock = goods.SaleStock;
        }
        else
        {
            // 非无限赏类型（箱号类型）：从奖品汇总计算库存
            if (stockSummary != null && stockSummary.TryGetValue(goods.Id, out var summary))
            {
                stock = summary.TotalStock;
                saleStock = summary.TotalStock - summary.SurplusStock;
            }
            else
            {
                // 没有奖品数据时，显示0
                stock = 0;
                saleStock = 0;
            }
        }

        return new GoodsListResponse
        {
            Id = goods.Id,
            Title = goods.Title,
            ImgUrl = goods.ImgUrl,
            Price = goods.Price,
            Type = goods.Type,
            TypeName = BoxTypeNames.GetValueOrDefault(goods.Type, "未知类型"),
            Status = goods.Status,
            Stock = stock,
            SaleStock = saleStock,
            Sort = goods.Sort,
            FlwStartTime = goods.FlwStartTime,
            FlwEndTime = goods.FlwEndTime,
            OpenTime = goods.OpenTime,
            ChoujiangXianzhi = goods.ChoujiangXianzhi,
            UnlockAmount = goods.UnlockAmount,
            CreatedAt = goods.CreatedAt,
            UpdatedAt = goods.UpdatedAt
        };
    }

    /// <summary>
    /// 映射商品到详情响应
    /// </summary>
    private GoodsDetailResponse MapToGoodsDetailResponse(Good goods)
    {
        return new GoodsDetailResponse
        {
            Id = goods.Id,
            Title = goods.Title,
            ImgUrl = goods.ImgUrl,
            ImgUrlBanner = goods.ImgUrlBanner,
            ImgUrlDetail = goods.ImgUrlDetail,
            Price = goods.Price,
            Type = goods.Type,
            TypeName = BoxTypeNames.GetValueOrDefault(goods.Type, "未知类型"),
            Status = goods.Status,
            Stock = goods.Stock,
            SaleStock = goods.SaleStock,
            Sort = goods.Sort,
            CategoryId = goods.CategoryId,
            DailyLimit = goods.DailyXiangou,
            LockIs = goods.LockIs,
            LockTime = goods.LockTime,
            IntegralIs = goods.IntegralIs,
            ShowIs = goods.ShowIs,
            CouponIs = goods.CouponIs,
            CouponPro = goods.CouponPro,
            FlwStartTime = goods.FlwStartTime,
            FlwEndTime = goods.FlwEndTime,
            OpenTime = goods.OpenTime,
            ChoujiangXianzhi = goods.ChoujiangXianzhi,
            UnlockAmount = goods.UnlockAmount,
            GoodsDescribe = goods.GoodsDescribe,
            NewIs = goods.NewIs,
            IsShouZhe = goods.IsShouZhe,
            RageIs = goods.RageIs,
            Rage = goods.Rage,
            LingzhuIs = goods.LingzhuIs,
            LingzhuFan = goods.LingzhuFan,
            PrizeNum = goods.PrizeNum,
            IsFlw = goods.IsFlw,
            CreatedAt = goods.CreatedAt,
            UpdatedAt = goods.UpdatedAt
        };
    }

    /// <summary>
    /// 映射奖品到DTO
    /// </summary>
    private PrizeDto MapToPrizeDto(GoodsItem prize, Dictionary<int, PrizeLevelInfo>? prizeLevels = null, Dictionary<string, List<PrizeRewardItem>>? rewardsDict = null)
    {
        string? shangTitle = null;
        string? shangColor = null;

        if (prize.ShangId.HasValue && prizeLevels != null && prizeLevels.TryGetValue(prize.ShangId.Value, out var level))
        {
            shangTitle = level.Title;
            shangColor = level.Color;
        }

        // 获取奖励配置
        List<PrizeRewardItem>? rewards = null;
        if (!string.IsNullOrEmpty(prize.RewardId) && rewardsDict != null && rewardsDict.TryGetValue(prize.RewardId, out var rewardList))
        {
            rewards = rewardList;
        }

        return new PrizeDto
        {
            Id = prize.Id,
            GoodsId = prize.GoodsId,
            Num = prize.Num,
            Title = prize.Title,
            ImgUrl = prize.ImgUrl,
            ImgUrlDetail = prize.ImgUrlDetail,
            Stock = prize.Stock,
            SurplusStock = prize.SurplusStock,
            Price = prize.Price,
            Money = prize.Money,
            ScMoney = prize.ScMoney,
            RealPro = prize.RealPro,
            GoodsType = prize.GoodsType,
            Sort = prize.Sort,
            ShangId = prize.ShangId,
            ShangTitle = shangTitle,
            ShangColor = shangColor,
            RewardNum = prize.RewardNum,
            Rank = prize.Rank,
            GiveMoney = prize.GiveMoney,
            CardNo = prize.CardNo,
            PrizeCode = prize.PrizeCode,
            Type = prize.Type,
            LianJiType = prize.LianJiType,
            RewardId = prize.RewardId,
            Doubling = prize.Doubling,
            IsLingzhu = prize.IsLingzhu,
            GoodsListId = prize.GoodsListId,
            Rewards = rewards,
            CreatedAt = prize.CreatedAt,
            UpdatedAt = prize.UpdatedAt
        };
    }

    /// <summary>
    /// 生成唯一奖品编码
    /// </summary>
    public static string GeneratePrizeCode()
    {
        return $"PC{DateTime.Now:yyyyMMddHHmmss}{Guid.NewGuid().ToString("N")[..8].ToUpper()}";
    }

    /// <summary>
    /// 库存增加时复制奖品配置（正确处理宝箱子奖品的父子关系）
    /// </summary>
    private async Task CopyPrizeConfigurationsAsync(int goodsId, int stockIncrease)
    {
        // 获取第一箱的奖品配置（作为模板）
        var templatePrizes = await _dbContext.GoodsItems
            .AsNoTracking()
            .Where(gi => gi.GoodsId == goodsId && gi.Num == 1) // 只取第一箱作为模板
            .ToListAsync();

        if (!templatePrizes.Any())
        {
            return; // 没有奖品配置，无需复制
        }

        var now = DateTime.Now;

        // 获取当前最大箱号
        var maxNum = await _dbContext.GoodsItems
            .Where(gi => gi.GoodsId == goodsId)
            .MaxAsync(gi => gi.Num);

        // 分离父奖品和子奖品模板
        var parentTemplates = templatePrizes.Where(p => p.GoodsListId == 0).ToList();
        var childTemplates = templatePrizes.Where(p => p.GoodsListId > 0).ToList();

        // 为每个新增的箱号复制奖品配置
        for (int i = 0; i < stockIncrease; i++)
        {
            var newNum = maxNum + 1 + i;
            var oldToNewIdMap = new Dictionary<int, int>(); // 旧模板ID -> 新ID 映射

            // 第一步：复制父奖品
            foreach (var template in parentTemplates)
            {
                var newPrize = new GoodsItem
                {
                    GoodsId = goodsId,
                    Num = newNum,
                    Title = template.Title,
                    ImgUrl = template.ImgUrl,
                    ImgUrlDetail = template.ImgUrlDetail,
                    Stock = template.Stock,
                    SurplusStock = template.Stock,
                    Price = template.Price,
                    Money = template.Money,
                    ScMoney = template.ScMoney,
                    RealPro = template.RealPro,
                    GoodsType = template.GoodsType,
                    Sort = template.Sort,
                    ShangId = template.ShangId,
                    RewardNum = template.RewardNum,
                    Rank = template.Rank,
                    GiveMoney = template.GiveMoney,
                    CardNo = template.CardNo,
                    PrizeCode = template.PrizeCode, // 保持相同的 prize_code，表示是同一个奖品配置
                    Type = template.Type,
                    LianJiType = template.LianJiType,
                    RewardId = template.RewardId,
                    Doubling = template.Doubling,
                    IsLingzhu = template.IsLingzhu,
                    PrizeNum = template.PrizeNum,
                    GoodsListId = 0,
                    SpecialStock = template.SpecialStock,
                    CreatedAt = now,
                    UpdatedAt = now
                };
                _dbContext.GoodsItems.Add(newPrize);
                await _dbContext.SaveChangesAsync(); // 保存以获取新ID
                oldToNewIdMap[template.Id] = newPrize.Id;
            }

            // 第二步：复制子奖品，并更新 goods_list_id 为新的父奖品ID
            foreach (var template in childTemplates)
            {
                var newParentId = oldToNewIdMap.GetValueOrDefault(template.GoodsListId, 0);
                if (newParentId == 0)
                {
                    _logger.LogWarning("复制奖品配置时找不到子奖品的父奖品映射: GoodsId={GoodsId}, TemplateChildId={TemplateChildId}, TemplateParentId={TemplateParentId}",
                        goodsId, template.Id, template.GoodsListId);
                    continue;
                }

                var newPrize = new GoodsItem
                {
                    GoodsId = goodsId,
                    Num = newNum,
                    Title = template.Title,
                    ImgUrl = template.ImgUrl,
                    ImgUrlDetail = template.ImgUrlDetail,
                    Stock = template.Stock,
                    SurplusStock = template.Stock,
                    Price = template.Price,
                    Money = template.Money,
                    ScMoney = template.ScMoney,
                    RealPro = template.RealPro,
                    GoodsType = template.GoodsType,
                    Sort = template.Sort,
                    ShangId = template.ShangId,
                    RewardNum = template.RewardNum,
                    Rank = template.Rank,
                    GiveMoney = template.GiveMoney,
                    CardNo = template.CardNo,
                    PrizeCode = template.PrizeCode, // 保持相同的 prize_code
                    Type = template.Type,
                    LianJiType = template.LianJiType,
                    RewardId = template.RewardId,
                    Doubling = template.Doubling,
                    IsLingzhu = template.IsLingzhu,
                    PrizeNum = template.PrizeNum,
                    GoodsListId = newParentId, // 使用新的父奖品ID
                    SpecialStock = template.SpecialStock,
                    CreatedAt = now,
                    UpdatedAt = now
                };
                _dbContext.GoodsItems.Add(newPrize);
            }
        }

        await _dbContext.SaveChangesAsync();
        _logger.LogInformation("复制奖品配置: GoodsId={GoodsId}, StockIncrease={StockIncrease}, NewBoxes={NewBoxes}",
            goodsId, stockIncrease, stockIncrease);
    }

    /// <summary>
    /// 记录商品操作日志
    /// </summary>
    private async Task LogGoodsOperationAsync(int goodsId, string operation, string content, int operatorId)
    {
        var log = new AdminOperationLog
        {
            AdminId = operatorId,
            Operation = $"goods:{operation}",
            Content = $"GoodsId={goodsId}, {content}",
            Ip = string.Empty,
            CreatedAt = DateTime.Now
        };

        _dbContext.AdminOperationLogs.Add(log);
        await _dbContext.SaveChangesAsync();
    }

    #endregion

    #region 盒子扩展设置

    /// <inheritdoc />
    public async Task<GoodsExtendDto> GetGoodsExtendAsync(int goodsId)
    {
        // 验证盒子存在
        var goods = await _dbContext.Goods
            .AsNoTracking()
            .Where(g => g.Id == goodsId && g.DeletedAt == null)
            .Select(g => new { g.Id, g.Type })
            .FirstOrDefaultAsync();

        if (goods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子不存在");
        }

        // 1. 先尝试从goods_extensions表获取盒子特定配置
        var goodsExtend = await _dbContext.GoodsExtensions
            .AsNoTracking()
            .Where(ge => ge.GoodsId == goodsId)
            .Select(ge => new GoodsExtendDto
            {
                Id = ge.Id,
                GoodsId = ge.GoodsId,
                PayWechat = ge.PayWechat,
                PayBalance = ge.PayBalance,
                PayCurrency = ge.PayCurrency,
                PayCurrency2 = ge.PayCurrency2,
                PayCoupon = ge.PayCoupon,
                IsDeduction = ge.IsDeduction,
                IsInherited = false
            })
            .FirstOrDefaultAsync();

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

        // 2. 如果没有盒子特定配置，从goods_types表获取类型默认配置
        var typeConfig = await _dbContext.GoodsTypes
            .AsNoTracking()
            .Where(gt => gt.Value == goods.Type)
            .Select(gt => new GoodsExtendDto
            {
                Id = 0,
                GoodsId = goodsId,
                PayWechat = gt.PayWechat,
                PayBalance = gt.PayBalance,
                PayCurrency = gt.PayCurrency,
                PayCurrency2 = gt.PayCurrency2,
                PayCoupon = gt.PayCoupon,
                IsDeduction = gt.IsDeduction,
                IsInherited = true
            })
            .FirstOrDefaultAsync();

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

        // 3. 如果都没有找到，返回默认值（全部启用）
        return new GoodsExtendDto
        {
            Id = 0,
            GoodsId = goodsId,
            PayWechat = 1,
            PayBalance = 1,
            PayCurrency = 1,
            PayCurrency2 = 1,
            PayCoupon = 1,
            IsDeduction = 1,
            IsInherited = true
        };
    }

    /// <inheritdoc />
    public async Task<bool> UpdateGoodsExtendAsync(int goodsId, GoodsExtendUpdateRequest request)
    {
        // 验证盒子存在
        var goodsExists = await _dbContext.Goods.AnyAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (!goodsExists)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子不存在");
        }

        // 查找现有扩展配置
        var existingExtend = await _dbContext.GoodsExtensions
            .FirstOrDefaultAsync(ge => ge.GoodsId == goodsId);

        if (existingExtend != null)
        {
            // 更新现有配置
            existingExtend.PayWechat = (byte)request.PayWechat;
            existingExtend.PayBalance = (byte)request.PayBalance;
            existingExtend.PayCurrency = (byte)request.PayCurrency;
            existingExtend.PayCurrency2 = (byte)request.PayCurrency2;
            existingExtend.PayCoupon = (byte)request.PayCoupon;
            existingExtend.IsDeduction = (byte)request.IsDeduction;
        }
        else
        {
            // 创建新配置
            var newExtend = new GoodsExtension
            {
                GoodsId = goodsId,
                PayWechat = (byte)request.PayWechat,
                PayBalance = (byte)request.PayBalance,
                PayCurrency = (byte)request.PayCurrency,
                PayCurrency2 = (byte)request.PayCurrency2,
                PayCoupon = (byte)request.PayCoupon,
                IsDeduction = (byte)request.IsDeduction
            };
            _dbContext.GoodsExtensions.Add(newExtend);
        }

        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("更新盒子扩展设置: GoodsId={GoodsId}", goodsId);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> DeleteGoodsExtendAsync(int goodsId)
    {
        // 验证盒子存在
        var goodsExists = await _dbContext.Goods.AnyAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (!goodsExists)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子不存在");
        }

        // 查找并删除扩展配置
        var existingExtend = await _dbContext.GoodsExtensions
            .FirstOrDefaultAsync(ge => ge.GoodsId == goodsId);

        if (existingExtend == null)
        {
            // 没有独立配置，无需删除
            return true;
        }

        _dbContext.GoodsExtensions.Remove(existingExtend);
        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("删除盒子扩展设置: GoodsId={GoodsId}", goodsId);

        return result;
    }

    #endregion

    #region 盒子操作

    /// <inheritdoc />
    public async Task<int> CopyGoodsAsync(int goodsId, int operatorId)
    {
        // 获取源盒子
        var sourceGoods = await _dbContext.Goods
            .AsNoTracking()
            .FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);

        if (sourceGoods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子不存在");
        }

        var now = DateTime.Now;

        // 创建新盒子（复制基本信息）
        var newGoods = new Good
        {
            Title = $"{sourceGoods.Title}_副本",
            Price = sourceGoods.Price,
            Type = sourceGoods.Type,
            ImgUrl = sourceGoods.ImgUrl,
            ImgUrlDetail = sourceGoods.ImgUrlDetail,
            Stock = sourceGoods.Stock,
            SaleStock = 0, // 新盒子销量为0
            Sort = sourceGoods.Sort,
            DailyXiangou = sourceGoods.DailyXiangou,
            LockIs = sourceGoods.LockIs,
            LockTime = sourceGoods.LockTime,
            IntegralIs = sourceGoods.IntegralIs,
            ShowIs = sourceGoods.ShowIs,
            CouponIs = sourceGoods.CouponIs,
            CouponPro = sourceGoods.CouponPro,
            FlwStartTime = sourceGoods.FlwStartTime,
            FlwEndTime = sourceGoods.FlwEndTime,
            OpenTime = sourceGoods.OpenTime,
            ChoujiangXianzhi = sourceGoods.ChoujiangXianzhi,
            CategoryId = sourceGoods.CategoryId,
            GoodsDescribe = sourceGoods.GoodsDescribe,
            NewIs = sourceGoods.NewIs,
            IsShouZhe = sourceGoods.IsShouZhe,
            RageIs = sourceGoods.RageIs,
            Rage = sourceGoods.Rage,
            LingzhuIs = sourceGoods.LingzhuIs,
            LingzhuFan = sourceGoods.LingzhuFan,
            Status = 0, // 新盒子默认下架
            PrizeNum = 0,
            IsFlw = sourceGoods.IsFlw,
            QuanjuXiangou = sourceGoods.QuanjuXiangou,
            IsAutoXiajia = sourceGoods.IsAutoXiajia,
            XiajiaLirun = sourceGoods.XiajiaLirun,
            XiajiaAutoCoushu = sourceGoods.XiajiaAutoCoushu,
            XiajiaJine = sourceGoods.XiajiaJine,
            UnlockAmount = sourceGoods.UnlockAmount,
            ItemCardId = sourceGoods.ItemCardId,
            LianJiNum = sourceGoods.LianJiNum,
            LianJiShangId = sourceGoods.LianJiShangId,
            LingzhuShangId = sourceGoods.LingzhuShangId,
            CreatedAt = now,
            UpdatedAt = now
        };

        _dbContext.Goods.Add(newGoods);
        await _dbContext.SaveChangesAsync();

        // 复制奖品（需要正确处理宝箱子奖品的父子关系）
        var sourcePrizes = await _dbContext.GoodsItems
            .AsNoTracking()
            .Where(gi => gi.GoodsId == goodsId)
            .ToListAsync();

        if (sourcePrizes.Any())
        {
            // 第一步：先复制所有父奖品（goods_list_id = 0）
            var parentPrizes = sourcePrizes.Where(p => p.GoodsListId == 0).ToList();
            var oldToNewIdMap = new Dictionary<int, int>(); // 旧ID -> 新ID 映射

            foreach (var p in parentPrizes)
            {
                var newPrize = new GoodsItem
                {
                    GoodsId = newGoods.Id,
                    Num = p.Num,
                    Title = p.Title,
                    ImgUrl = p.ImgUrl,
                    ImgUrlDetail = p.ImgUrlDetail,
                    Stock = p.Stock,
                    SurplusStock = p.Stock, // 重置剩余库存
                    Price = p.Price,
                    Money = p.Money,
                    ScMoney = p.ScMoney,
                    RealPro = p.RealPro,
                    GoodsType = p.GoodsType,
                    Sort = p.Sort,
                    ShangId = p.ShangId,
                    RewardNum = p.RewardNum,
                    Rank = p.Rank,
                    GiveMoney = p.GiveMoney,
                    CardNo = p.CardNo,
                    PrizeCode = GeneratePrizeCode(),
                    Type = p.Type,
                    LianJiType = p.LianJiType,
                    RewardId = p.RewardId,
                    Doubling = p.Doubling,
                    IsLingzhu = p.IsLingzhu,
                    PrizeNum = p.PrizeNum,
                    GoodsListId = 0,
                    SpecialStock = p.SpecialStock,
                    CreatedAt = now,
                    UpdatedAt = now
                };
                _dbContext.GoodsItems.Add(newPrize);
                await _dbContext.SaveChangesAsync(); // 保存以获取新ID
                oldToNewIdMap[p.Id] = newPrize.Id;
            }

            // 第二步：复制所有子奖品（goods_list_id > 0），并更新 goods_list_id 为新的父奖品ID
            var childPrizes = sourcePrizes.Where(p => p.GoodsListId > 0).ToList();
            foreach (var p in childPrizes)
            {
                // 查找新的父奖品ID
                var newParentId = oldToNewIdMap.GetValueOrDefault(p.GoodsListId, 0);
                if (newParentId == 0)
                {
                    _logger.LogWarning("复制盒子时找不到子奖品的父奖品映射: SourceChildId={SourceChildId}, SourceParentId={SourceParentId}",
                        p.Id, p.GoodsListId);
                    continue; // 跳过找不到父奖品的子奖品
                }

                var newPrize = new GoodsItem
                {
                    GoodsId = newGoods.Id,
                    Num = p.Num,
                    Title = p.Title,
                    ImgUrl = p.ImgUrl,
                    ImgUrlDetail = p.ImgUrlDetail,
                    Stock = p.Stock,
                    SurplusStock = p.Stock, // 重置剩余库存
                    Price = p.Price,
                    Money = p.Money,
                    ScMoney = p.ScMoney,
                    RealPro = p.RealPro,
                    GoodsType = p.GoodsType,
                    Sort = p.Sort,
                    ShangId = p.ShangId,
                    RewardNum = p.RewardNum,
                    Rank = p.Rank,
                    GiveMoney = p.GiveMoney,
                    CardNo = p.CardNo,
                    PrizeCode = GeneratePrizeCode(),
                    Type = p.Type,
                    LianJiType = p.LianJiType,
                    RewardId = p.RewardId,
                    Doubling = p.Doubling,
                    IsLingzhu = p.IsLingzhu,
                    PrizeNum = p.PrizeNum,
                    GoodsListId = newParentId, // 使用新的父奖品ID
                    SpecialStock = p.SpecialStock,
                    CreatedAt = now,
                    UpdatedAt = now
                };
                _dbContext.GoodsItems.Add(newPrize);
            }

            await _dbContext.SaveChangesAsync();

            // 更新新盒子的奖品数量（只统计父奖品）
            newGoods.PrizeNum = parentPrizes.Count;
        }

        // 复制扩展设置（如果有）
        var sourceExtend = await _dbContext.GoodsExtensions
            .AsNoTracking()
            .FirstOrDefaultAsync(ge => ge.GoodsId == goodsId);

        if (sourceExtend != null)
        {
            var newExtend = new GoodsExtension
            {
                GoodsId = newGoods.Id,
                PayWechat = sourceExtend.PayWechat,
                PayBalance = sourceExtend.PayBalance,
                PayCurrency = sourceExtend.PayCurrency,
                PayCurrency2 = sourceExtend.PayCurrency2,
                PayCoupon = sourceExtend.PayCoupon,
                IsDeduction = sourceExtend.IsDeduction
            };
            _dbContext.GoodsExtensions.Add(newExtend);
        }

        await _dbContext.SaveChangesAsync();

        // 记录操作日志
        await LogGoodsOperationAsync(newGoods.Id, "copy", $"复制盒子: 源ID={goodsId}, 新ID={newGoods.Id}", operatorId);

        _logger.LogInformation("复制盒子成功: SourceId={SourceId}, NewId={NewId}, Operator={Operator}",
            goodsId, newGoods.Id, operatorId);

        return newGoods.Id;
    }

    /// <inheritdoc />
    public async Task<bool> ClearGoodsLotteryAsync(int goodsId, int operatorId)
    {
        // 验证盒子存在
        var goods = await _dbContext.Goods.FirstOrDefaultAsync(g => g.Id == goodsId && g.DeletedAt == null);
        if (goods == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "盒子不存在");
        }

        // 使用事务确保数据一致性
        using var transaction = await _dbContext.Database.BeginTransactionAsync();

        try
        {
            // 1. 重置盒子销量
            goods.SaleStock = 0;
            goods.UpdatedAt = DateTime.Now;

            // 2. 重置所有奖品的剩余库存
            var prizes = await _dbContext.GoodsItems
                .Where(gi => gi.GoodsId == goodsId)
                .ToListAsync();

            foreach (var prize in prizes)
            {
                prize.SurplusStock = prize.Stock;
                prize.UpdatedAt = DateTime.Now;
            }

            // 3. 删除抽奖记录（如果有lottery_records表）
            // 注意：这里需要根据实际的抽奖记录表结构来实现
            // 暂时只重置库存，抽奖记录的清理可能需要额外处理

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

            // 记录操作日志
            await LogGoodsOperationAsync(goodsId, "clear_lottery", $"清空抽奖记录: {goods.Title}", operatorId);

            _logger.LogInformation("清空盒子抽奖记录: GoodsId={GoodsId}, Operator={Operator}", goodsId, operatorId);

            return true;
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "清空盒子抽奖记录失败: GoodsId={GoodsId}", goodsId);
            throw;
        }
    }

    #endregion
}
