using HoneyBox.Admin.Business.Models;
using HoneyBox.Admin.Business.Models.DesignatedPrize;
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 DesignatedPrizeService : IDesignatedPrizeService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly ILogger<DesignatedPrizeService> _logger;

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

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

        var configs = await _dbContext.GoodsDesignatedPrizes
            .AsNoTracking()
            .Include(dp => dp.GoodsItem)
            .Include(dp => dp.User)
            .Where(dp => dp.GoodsId == goodsId)
            .OrderByDescending(dp => dp.CreatedAt)
            .ToListAsync();

        return configs.Select(MapToDto).ToList();
    }

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

        // 验证奖品存在且属于该商品
        var goodsItem = await _dbContext.GoodsItems
            .AsNoTracking()
            .FirstOrDefaultAsync(gi => gi.Id == request.GoodsItemId && gi.GoodsId == goodsId);
        if (goodsItem == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "奖品不存在");
        }

        // 验证用户存在
        var user = await _dbContext.Users
            .AsNoTracking()
            .FirstOrDefaultAsync(u => u.Id == request.UserId);
        if (user == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "用户不存在");
        }


        // 检查唯一约束：同一商品的同一奖品只能指定给一个用户
        var existingConfig = await _dbContext.GoodsDesignatedPrizes
            .AnyAsync(dp => dp.GoodsId == goodsId && dp.GoodsItemId == request.GoodsItemId);
        if (existingConfig)
        {
            throw new BusinessException(BusinessErrorCodes.Conflict, "该奖品已配置指定用户");
        }

        var now = DateTime.Now;
        var config = new GoodsDesignatedPrize
        {
            GoodsId = goodsId,
            GoodsItemId = request.GoodsItemId,
            UserId = request.UserId,
            IsActive = true,
            Remark = request.Remark,
            CreatedAt = now,
            UpdatedAt = now
        };

        _dbContext.GoodsDesignatedPrizes.Add(config);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation(
            "创建指定中奖配置成功: ConfigId={ConfigId}, GoodsId={GoodsId}, GoodsItemId={GoodsItemId}, UserId={UserId}",
            config.Id, goodsId, request.GoodsItemId, request.UserId);

        // 重新查询以获取关联数据
        return await GetByIdAsync(config.Id);
    }

    /// <inheritdoc />
    public async Task<DesignatedPrizeDto> UpdateAsync(int id, UpdateDesignatedPrizeRequest request)
    {
        var config = await _dbContext.GoodsDesignatedPrizes
            .Include(dp => dp.GoodsItem)
            .Include(dp => dp.User)
            .FirstOrDefaultAsync(dp => dp.Id == id);

        if (config == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "配置不存在");
        }

        // 如果要更新用户ID，验证用户存在
        if (request.UserId.HasValue && request.UserId.Value != config.UserId)
        {
            var userExists = await _dbContext.Users.AnyAsync(u => u.Id == request.UserId.Value);
            if (!userExists)
            {
                throw new BusinessException(BusinessErrorCodes.NotFound, "用户不存在");
            }
            config.UserId = request.UserId.Value;
        }

        if (request.IsActive.HasValue)
        {
            config.IsActive = request.IsActive.Value;
        }

        if (request.Remark != null)
        {
            config.Remark = request.Remark;
        }

        config.UpdatedAt = DateTime.Now;

        await _dbContext.SaveChangesAsync();

        _logger.LogInformation(
            "更新指定中奖配置成功: ConfigId={ConfigId}, IsActive={IsActive}",
            id, config.IsActive);

        // 重新查询以获取最新关联数据
        return await GetByIdAsync(id);
    }

    /// <inheritdoc />
    public async Task<bool> DeleteAsync(int id)
    {
        var config = await _dbContext.GoodsDesignatedPrizes.FirstOrDefaultAsync(dp => dp.Id == id);
        if (config == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "配置不存在");
        }

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

        _logger.LogInformation(
            "删除指定中奖配置成功: ConfigId={ConfigId}, GoodsId={GoodsId}, GoodsItemId={GoodsItemId}",
            id, config.GoodsId, config.GoodsItemId);

        return result;
    }

    #region Private Helper Methods

    /// <summary>
    /// 根据ID获取配置详情
    /// </summary>
    private async Task<DesignatedPrizeDto> GetByIdAsync(int id)
    {
        var config = await _dbContext.GoodsDesignatedPrizes
            .AsNoTracking()
            .Include(dp => dp.GoodsItem)
            .Include(dp => dp.User)
            .FirstOrDefaultAsync(dp => dp.Id == id);

        if (config == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "配置不存在");
        }

        return MapToDto(config);
    }

    /// <summary>
    /// 映射实体到DTO
    /// </summary>
    private static DesignatedPrizeDto MapToDto(GoodsDesignatedPrize entity)
    {
        return new DesignatedPrizeDto
        {
            Id = entity.Id,
            GoodsId = entity.GoodsId,
            GoodsItemId = entity.GoodsItemId,
            GoodsItemTitle = entity.GoodsItem?.Title,
            GoodsItemImgUrl = entity.GoodsItem?.ImgUrl,
            UserId = entity.UserId,
            UserNickname = entity.User?.Nickname,
            UserPhone = entity.User?.Mobile,
            IsActive = entity.IsActive,
            Remark = entity.Remark,
            CreatedAt = entity.CreatedAt
        };
    }

    #endregion
}
