using Medallion.Threading;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Users;
using Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
using Yi.Framework.AiHub.Application.Contracts.Dtos.Recharge;
using Yi.Framework.AiHub.Application.Contracts.IServices;
using Yi.Framework.AiHub.Domain.Managers;
using Yi.Framework.AiHub.Domain.Shared.Enums;

namespace Yi.Framework.AiHub.Application.Services;

/// <summary>
/// 激活码服务
/// </summary>
public class ActivationCodeService : ApplicationService, IActivationCodeService
{
    private readonly ActivationCodeManager _activationCodeManager;
    private readonly IRechargeService _rechargeService;
    private readonly PremiumPackageManager _premiumPackageManager;
    private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
    public ActivationCodeService(
        ActivationCodeManager activationCodeManager,
        IRechargeService rechargeService,
        PremiumPackageManager premiumPackageManager)
    {
        _activationCodeManager = activationCodeManager;
        _rechargeService = rechargeService;
        _premiumPackageManager = premiumPackageManager;
    }

    /// <summary>
    /// 批量生成激活码
    /// </summary>
    [Authorize]
    [HttpPost("activationCode/Batch")]
    public async Task<ActivationCodeCreateListOutput> CreateBatchAsync(ActivationCodeCreateListInput input)
    {
        if (input.Items == null || input.Items.Count == 0)
        {
            throw new UserFriendlyException("生成列表不能为空");
        }

        var entities = await _activationCodeManager.CreateBatchAsync(
            input.Items.Select(x => (x.GoodsType, x.Count)).ToList());

        var outputs = entities
            .GroupBy(x => x.GoodsType)
            .Select(group => new ActivationCodeCreateOutput
            {
                GoodsType = group.Key,
                Count = group.Count(),
                Codes = group.Select(x => x.Code).ToList()
            })
            .ToList();

        return new ActivationCodeCreateListOutput
        {
            Items = outputs
        };
    }

    /// <summary>
    /// 兑换激活码
    /// </summary>
    [Authorize]
    [HttpPost("activationCode/Redeem")]
    public async Task<ActivationCodeRedeemOutput> RedeemAsync(ActivationCodeRedeemInput input)
    {
        //自旋等待，防抖
        await using var handle =
            await DistributedLock.AcquireLockAsync($"Yi:AiHub:ActivationCodeLock:{input.Code}");
        
        var userId = CurrentUser.GetId();
        var redeemContext = await _activationCodeManager.RedeemAsync(userId, input.Code);
        var goodsType = redeemContext.ActivationCode.GoodsType;
        var goods = redeemContext.Goods;
        var packageName = redeemContext.PackageName;
        var totalAmount = goods.Price;

        if (goods.TokenAmount > 0)
        {
            await _premiumPackageManager.CreatePremiumPackageAsync(
                userId,
                goods.TokenAmount,
                packageName,
                totalAmount,
                "激活码兑换",
                expireMonths: null,
                isCreateRechargeRecord: !goods.IsCombo);
        }

        if (goods.VipMonths > 0 || goods.VipDays > 0)
        {
            await _rechargeService.RechargeVipAsync(new RechargeCreateInput
            {
                UserId = userId,
                RechargeAmount = totalAmount,
                Content = packageName,
                Months = goods.VipMonths,
                Days = goods.VipDays,
                Remark = "激活码兑换",
                ContactInfo = null
            });
        }

        return new ActivationCodeRedeemOutput
        {
            GoodsType = goodsType,
            PackageName = packageName,
            Content = packageName
        };
    }
}
