using HoneyBox.Admin.Business.Models;
using HoneyBox.Admin.Business.Models.Coupon;
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 CouponService : ICouponService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly ILogger<CouponService> _logger;

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

    /// <inheritdoc />
    public async Task<PagedResult<CouponResponse>> GetCouponsAsync(CouponListRequest request)
    {
        var query = _dbContext.Coupons.AsNoTracking();

        // 应用关键词过滤
        if (!string.IsNullOrWhiteSpace(request.Keyword))
        {
            query = query.Where(c => c.Title.Contains(request.Keyword));
        }

        // 应用类型过滤
        if (request.Type.HasValue)
        {
            query = query.Where(c => c.Type == request.Type.Value);
        }

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

        // 获取列表
        var coupons = await query
            .OrderByDescending(c => c.Id)
            .Skip(request.Skip)
            .Take(request.PageSize)
            .ToListAsync();

        // 映射结果
        var list = coupons.Select(MapToResponse).ToList();

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

    /// <inheritdoc />
    public async Task<CouponResponse?> GetCouponByIdAsync(int id)
    {
        var coupon = await _dbContext.Coupons
            .AsNoTracking()
            .FirstOrDefaultAsync(c => c.Id == id);

        return coupon == null ? null : MapToResponse(coupon);
    }


    /// <inheritdoc />
    public async Task<int> CreateCouponAsync(CouponCreateRequest request)
    {
        // 验证必填字段
        ValidateRequest(request);

        var now = DateTime.Now;
        var coupon = new Coupon
        {
            Title = request.Title,
            ManPrice = request.MinPrice,
            Price = request.DiscountPrice,
            EffectiveDay = request.ValidDays,
            Type = (byte)request.Type,
            Ttype = (byte)request.UseLimit,
            Status = 1, // 默认启用
            CreatedAt = now
        };

        _dbContext.Coupons.Add(coupon);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("创建优惠券成功: Id={Id}, Title={Title}", coupon.Id, coupon.Title);

        return coupon.Id;
    }

    /// <inheritdoc />
    public async Task<bool> UpdateCouponAsync(int id, CouponUpdateRequest request)
    {
        var coupon = await _dbContext.Coupons.FirstOrDefaultAsync(c => c.Id == id);
        if (coupon == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "优惠券不存在");
        }

        // 验证必填字段
        ValidateRequest(request);

        coupon.Title = request.Title;
        coupon.ManPrice = request.MinPrice;
        coupon.Price = request.DiscountPrice;
        coupon.EffectiveDay = request.ValidDays;
        coupon.Type = (byte)request.Type;
        coupon.Ttype = (byte)request.UseLimit;

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

        _logger.LogInformation("更新优惠券成功: Id={Id}, Title={Title}", id, coupon.Title);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> DeleteCouponAsync(int id)
    {
        var coupon = await _dbContext.Coupons.FirstOrDefaultAsync(c => c.Id == id);
        if (coupon == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "优惠券不存在");
        }

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

        _logger.LogInformation("删除优惠券成功: Id={Id}, Title={Title}", id, coupon.Title);

        return result;
    }

    /// <inheritdoc />
    public async Task<bool> UpdateCouponStatusAsync(int id, int status)
    {
        var coupon = await _dbContext.Coupons.FirstOrDefaultAsync(c => c.Id == id);
        if (coupon == null)
        {
            throw new BusinessException(BusinessErrorCodes.NotFound, "优惠券不存在");
        }

        coupon.Status = (byte)status;
        var result = await _dbContext.SaveChangesAsync() > 0;

        _logger.LogInformation("更新优惠券状态成功: Id={Id}, Status={Status}", id, status);

        return result;
    }

    /// <inheritdoc />
    public async Task<PagedResult<CouponReceiveResponse>> GetCouponReceivesAsync(CouponReceiveListRequest request)
    {
        var query = from cr in _dbContext.CouponReceives.AsNoTracking()
                    join u in _dbContext.Users.AsNoTracking() on cr.UserId equals u.Id into userJoin
                    from user in userJoin.DefaultIfEmpty()
                    select new { CouponReceive = cr, User = user };

        // 应用用户ID过滤
        if (request.UserId.HasValue)
        {
            query = query.Where(x => x.CouponReceive.UserId == request.UserId.Value);
        }

        // 应用标题过滤
        if (!string.IsNullOrWhiteSpace(request.Title))
        {
            query = query.Where(x => x.CouponReceive.Title.Contains(request.Title));
        }

        // 应用状态过滤
        if (request.Status.HasValue)
        {
            var now = DateTime.Now;
            switch (request.Status.Value)
            {
                case CouponReceiveStatus.Unused:
                    // 未使用：State=0 且未过期
                    query = query.Where(x => x.CouponReceive.State == 0 && 
                        (x.CouponReceive.EndTime == null || x.CouponReceive.EndTime > now));
                    break;
                case CouponReceiveStatus.Used:
                    // 已使用：State=1
                    query = query.Where(x => x.CouponReceive.State == 1);
                    break;
                case CouponReceiveStatus.Expired:
                    // 已过期：State=0 且已过期
                    query = query.Where(x => x.CouponReceive.State == 0 && 
                        x.CouponReceive.EndTime != null && x.CouponReceive.EndTime <= now);
                    break;
            }
        }

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

        // 获取列表
        var records = await query
            .OrderByDescending(x => x.CouponReceive.Id)
            .Skip(request.Skip)
            .Take(request.PageSize)
            .ToListAsync();

        // 映射结果
        var now2 = DateTime.Now;
        var list = records.Select(x => MapToReceiveResponse(x.CouponReceive, x.User, now2)).ToList();

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


    #region Private Helper Methods

    /// <summary>
    /// 验证请求参数
    /// </summary>
    private void ValidateRequest(CouponCreateRequest request)
    {
        if (string.IsNullOrWhiteSpace(request.Title))
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "优惠券标题不能为空");
        }

        if (request.MinPrice < 0)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "满减门槛金额不能为负数");
        }

        if (request.DiscountPrice <= 0)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "优惠金额必须大于0");
        }

        if (request.ValidDays <= 0)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "有效期必须大于0天");
        }

        if (request.Type < 1 || request.Type > 3)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "优惠券类型无效");
        }

        if (request.UseLimit < 0 || request.UseLimit > 6)
        {
            throw new BusinessException(BusinessErrorCodes.ValidationFailed, "使用限制类型无效");
        }
    }

    /// <summary>
    /// 映射优惠券实体到响应模型
    /// </summary>
    private CouponResponse MapToResponse(Coupon coupon)
    {
        return new CouponResponse
        {
            Id = coupon.Id,
            Title = coupon.Title,
            MinPrice = coupon.ManPrice ?? 0,
            DiscountPrice = coupon.Price ?? 0,
            ValidDays = coupon.EffectiveDay ?? 0,
            Type = coupon.Type ?? 0,
            TypeName = CouponTypes.GetTypeName(coupon.Type ?? 0),
            UseLimit = coupon.Ttype ?? 0,
            UseLimitName = CouponUseLimits.GetLimitName(coupon.Ttype ?? 0),
            Status = coupon.Status,
            CreatedAt = coupon.CreatedAt
        };
    }

    /// <summary>
    /// 映射领取记录实体到响应模型
    /// </summary>
    private CouponReceiveResponse MapToReceiveResponse(CouponReceife receive, User? user, DateTime now)
    {
        // 计算状态
        int status;
        if (receive.State == 1)
        {
            status = CouponReceiveStatus.Used;
        }
        else if (receive.EndTime.HasValue && receive.EndTime.Value <= now)
        {
            status = CouponReceiveStatus.Expired;
        }
        else
        {
            status = CouponReceiveStatus.Unused;
        }

        return new CouponReceiveResponse
        {
            Id = receive.Id,
            UserId = receive.UserId ?? 0,
            Uid = user?.Uid ?? "",
            Nickname = user?.Nickname ?? "",
            CouponTitle = receive.Title,
            MinPrice = receive.ManPrice ?? 0,
            DiscountPrice = receive.Price ?? 0,
            Status = status,
            StatusName = CouponReceiveStatus.GetStatusName(status),
            ExpireTime = receive.EndTime,
            CreatedAt = receive.CreatedAt
        };
    }

    #endregion
}
