using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Models.Goods;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Core.Services;

/// <summary>
/// 奖品服务实现
/// </summary>
public class PrizeService : IPrizeService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly ILogger<PrizeService> _logger;

    // 抽奖赏品ID范围 [10, 33]
    private static readonly int[] ShangPrizeIdRange = { 10, 33 };
    // 赠送赏品ID (不计入统计)
    private static readonly int[] ShangGiveIds = { 1, 2, 3, 4, 5 };

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

    /// <inheritdoc />
    public async Task<PrizeCountResponseDto> GetPrizeCountAsync(int goodsId)
    {
        // 1. 验证商品存在且状态有效
        var goods = await _dbContext.Goods
            .Where(g => g.Id == goodsId && g.DeletedAt == null)
            .Select(g => new { g.Id, g.Status })
            .FirstOrDefaultAsync();

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

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

        // 2. 按赏品分类统计数量
        var prizeStats = await _dbContext.GoodsItems
            .Where(gi => gi.GoodsId == goodsId
                && gi.GoodsListId == 0
                && gi.ShangId.HasValue
                && !ShangGiveIds.Contains(gi.ShangId.Value))
            .GroupBy(gi => gi.ShangId)
            .Select(g => new
            {
                ShangId = g.Key ?? 0,
                Total = g.Sum(x => x.Stock),
                Surplus = g.Sum(x => x.SurplusStock)
            })
            .OrderBy(x => x.ShangId)
            .ToListAsync();

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

        // 4. 构建结果
        var list = prizeStats.Select(ps => new PrizeCountItemDto
        {
            ShangId = ps.ShangId,
            ShangInfo = shangInfos.TryGetValue(ps.ShangId, out var info) ? info : null,
            Total = ps.Total,
            Surplus = ps.Surplus
        }).ToList();

        return new PrizeCountResponseDto
        {
            List = list,
            Total = list.Sum(x => x.Total),
            Surplus = list.Sum(x => x.Surplus)
        };
    }

    /// <inheritdoc />
    public async Task<PrizeContentResponseDto> GetPrizeContentAsync(int goodsId, int num)
    {
        // 1. 验证商品存在且状态有效
        var goods = await _dbContext.Goods
            .Where(g => g.Id == goodsId && g.DeletedAt == null)
            .Select(g => new { g.Id, g.Status, g.Stock })
            .FirstOrDefaultAsync();

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

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

        // 验证箱号有效性
        if (num < 0 || num > goods.Stock)
        {
            throw new InvalidOperationException("箱号错误");
        }

        // 如果num为0，默认查询第1箱
        if (num == 0)
        {
            num = 1;
        }

        // 2. 获取本箱子总剩余库存（用于计算概率）
        var allSurplusStock = await _dbContext.GoodsItems
            .Where(gi => gi.GoodsId == goodsId
                && gi.Num == num
                && gi.GoodsListId == 0
                && gi.ShangId.HasValue
                && !ShangGiveIds.Contains(gi.ShangId.Value))
            .SumAsync(gi => gi.SurplusStock);

        // 3. 查询指定箱号的奖品列表
        var goodsItems = await _dbContext.GoodsItems
            .Where(gi => gi.GoodsId == goodsId
                && gi.Num == num
                && gi.GoodsListId == 0)
            .OrderByDescending(gi => gi.Sort)
            .ThenBy(gi => gi.ShangId)
            .ThenBy(gi => gi.Id)
            .Select(gi => new
            {
                gi.Id,
                gi.ShangId,
                gi.Title,
                gi.Stock,
                gi.SurplusStock,
                gi.ImgUrl,
                gi.GoodsType,
                gi.SaleTime,
                gi.Price,
                gi.ScMoney
            })
            .ToListAsync();

        // 4. 获取所有赏品等级信息
        var shangIds = goodsItems
            .Where(x => x.ShangId.HasValue)
            .Select(x => x.ShangId!.Value)
            .Distinct()
            .ToList();

        var shangInfos = await _dbContext.PrizeLevels
            .Where(p => shangIds.Contains(p.Id))
            .ToDictionaryAsync(p => p.Id, p => new ShangInfoDto
            {
                Id = p.Id,
                Title = p.Title,
                ImgUrl = FormatImageUrl(p.ImgUrl),
                Color = p.Color,
                SpecialImgUrl = FormatImageUrl(p.SpecialImgUrl)
            });

        // 5. 构建结果列表并计算概率
        var result = new List<GoodsListItemDto>();
        decimal proAll = 0;
        decimal proMax = 0;
        int proMaxIndex = 0;

        for (int i = 0; i < goodsItems.Count; i++)
        {
            var item = goodsItems[i];
            var shangId = item.ShangId ?? 0;
            var surplusStock = item.SurplusStock;

            string pro;
            decimal proNum = 0;

            // 赠送赏品不计入概率
            if (ShangGiveIds.Contains(shangId))
            {
                pro = "只赠不售";
            }
            else
            {
                if (surplusStock > 0 && allSurplusStock > 0)
                {
                    proNum = Math.Round((decimal)surplusStock / allSurplusStock * 100, 2);
                    pro = $"概率：{RemoveTrailingZeros(proNum)}%";
                }
                else
                {
                    pro = "概率：0%";
                }
            }

            // 计算剩余概率
            proAll += proNum;
            if (proNum >= proMax)
            {
                proMax = proNum;
                proMaxIndex = i;
            }

            var dto = new GoodsListItemDto
            {
                Id = item.Id,
                ShangId = shangId,
                ShangInfo = shangId > 0 && shangInfos.TryGetValue(shangId, out var info) ? info : null,
                Title = item.Title,
                Stock = item.Stock,
                SurplusStock = surplusStock,
                ImgUrl = FormatImageUrl(item.ImgUrl),
                GoodsType = item.GoodsType,
                Price = (item.Price * 1).ToString("0.##"),
                ScMoney = item.ScMoney.ToString("0.##"),
                SaleTime = item.SaleTime.HasValue ? item.SaleTime.Value.ToString("yyyy-MM-dd") : null,
                Pro = pro,
                Children = item.GoodsType == 4 // goods_type=4 表示有子奖品
            };

            result.Add(dto);
        }

        // 概率不足100%时，补足到最大概率的奖品
        if (proMax > 0 && proAll < 100 && result.Count > proMaxIndex)
        {
            var surplusPro = 100 - proAll;
            var newPro = proMax + surplusPro;
            result[proMaxIndex].Pro = $"概率：{RemoveTrailingZeros(newPro)}%";
        }

        return new PrizeContentResponseDto
        {
            List = result
        };
    }

    /// <inheritdoc />
    public async Task<PrizeLogsResponseDto> GetPrizeLogsAsync(int goodsId, int goodsNum, int shangId, int page, int pageSize)
    {
        // 1. 验证商品存在且状态有效
        var goods = await _dbContext.Goods
            .Where(g => g.Id == goodsId && g.DeletedAt == null)
            .Select(g => new { g.Id, g.Status, g.Type, g.Stock })
            .FirstOrDefaultAsync();

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

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

        // 验证箱号有效性
        if (goodsNum < 0)
        {
            throw new InvalidOperationException("箱号选择错误");
        }

        // 2. 获取中奖记录分类列表 (按shang_id分组)
        var categoryList = await _dbContext.GoodsItems
            .Where(gi => gi.GoodsId == goodsId && gi.Num == goodsNum)
            .Select(gi => gi.ShangId)
            .Distinct()
            .ToListAsync();

        // 获取赏品等级信息
        var shangIds = categoryList.Where(s => s.HasValue).Select(s => s!.Value).ToList();
        var shangInfos = await _dbContext.PrizeLevels
            .Where(p => shangIds.Contains(p.Id))
            .ToDictionaryAsync(p => p.Id, p => new { p.Title, p.Color });

        // 构建分类列表，添加"全部"选项
        var categories = new List<CategoryDto>
        {
            new CategoryDto { ShangId = 0, ShangTitle = "全部" }
        };
        
        foreach (var sid in categoryList.Where(s => s.HasValue).Select(s => s!.Value).OrderBy(s => s))
        {
            if (shangInfos.TryGetValue(sid, out var info))
            {
                categories.Add(new CategoryDto
                {
                    ShangId = sid,
                    ShangTitle = info.Title
                });
            }
        }

        // 3. 构建中奖记录查询
        var query = _dbContext.OrderItems
            .Where(oi => oi.GoodsId == goodsId
                && oi.Num == goodsNum
                && oi.OrderType == goods.Type
                && oi.Source == 1);

        // 如果指定了shang_id，添加筛选条件
        if (shangId > 0)
        {
            query = query.Where(oi => oi.ShangId == shangId);
        }

        // 4. 按order_id, goodslist_id, user_id分组，统计prize_num
        var groupedQuery = query
            .GroupBy(oi => new { oi.OrderId, oi.GoodslistId, oi.UserId })
            .Select(g => new
            {
                UserId = g.Key.UserId,
                GoodslistTitle = g.First().GoodslistTitle,
                GoodslistImgurl = g.First().GoodslistImgurl,
                ShangId = g.First().ShangId,
                Addtime = g.First().Addtime,
                PrizeNum = g.Count()
            })
            .OrderByDescending(x => x.Addtime);

        // 5. 计算总数和分页
        var totalCount = await query
            .GroupBy(oi => new { oi.OrderId, oi.GoodslistId, oi.UserId })
            .CountAsync();

        var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

        // 6. 获取分页数据
        var prizeLogData = await groupedQuery
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();

        // 7. 获取用户信息
        var userIds = prizeLogData.Select(x => x.UserId).Distinct().ToList();
        var users = await _dbContext.Users
            .Where(u => userIds.Contains(u.Id))
            .ToDictionaryAsync(u => u.Id, u => new { u.Nickname, u.HeadImg });

        // 8. 获取赏品颜色信息
        var prizeShangIds = prizeLogData.Select(x => x.ShangId).Distinct().ToList();
        var prizeShangInfos = await _dbContext.PrizeLevels
            .Where(p => prizeShangIds.Contains(p.Id))
            .ToDictionaryAsync(p => p.Id, p => new { p.Title, p.Color });

        // 9. 构建结果
        var data = prizeLogData.Select(item =>
        {
            var userInfo = users.TryGetValue(item.UserId, out var user)
                ? new PrizeLogUserDto
                {
                    Nickname = user.Nickname,
                    HeadImg = FormatImageUrl(user.HeadImg)
                }
                : null;

            var shangInfo = prizeShangInfos.TryGetValue(item.ShangId, out var shang) ? shang : null;

            return new PrizeLogDto
            {
                UserId = item.UserId,
                GoodslistTitle = item.GoodslistTitle ?? string.Empty,
                GoodslistImgurl = FormatImageUrl(item.GoodslistImgurl),
                ShangId = item.ShangId,
                Addtime = DateTimeOffset.FromUnixTimeSeconds(item.Addtime).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                PrizeNum = item.PrizeNum,
                ShangTitle = shangInfo?.Title ?? string.Empty,
                UserInfo = userInfo,
                ShangColor = shangInfo?.Color ?? string.Empty
            };
        }).ToList();

        return new PrizeLogsResponseDto
        {
            Category = categories,
            Data = data,
            LastPage = totalPages,
            Total = totalCount
        };
    }

    /// <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 static string RemoveTrailingZeros(decimal value)
    {
        return value.ToString("0.##");
    }
}
