using System.Text;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Yi.Framework.AiHub.Domain.Entities;
using Yi.Framework.AiHub.Domain.Shared.Enums;
using Yi.Framework.SqlSugarCore.Abstractions;

namespace Yi.Framework.AiHub.Domain.Managers;

public class ActivationCodeRedeemContext
{
    public ActivationCodeAggregateRoot ActivationCode { get; set; } = default!;
    public string PackageName { get; set; } = string.Empty;
    public ActivationCodeGoodsAttribute Goods { get; set; } = default!;
}

/// <summary>
/// 激活码管理器
/// </summary>
public class ActivationCodeManager : DomainService
{
    private readonly ISqlSugarRepository<ActivationCodeAggregateRoot, Guid> _activationCodeRepository;
    private readonly ISqlSugarRepository<ActivationCodeRecordAggregateRoot, Guid> _activationCodeRecordRepository;
    private readonly ILogger<ActivationCodeManager> _logger;

    public ActivationCodeManager(
        ISqlSugarRepository<ActivationCodeAggregateRoot, Guid> activationCodeRepository,
        ISqlSugarRepository<ActivationCodeRecordAggregateRoot, Guid> activationCodeRecordRepository,
        ILogger<ActivationCodeManager> logger)
    {
        _activationCodeRepository = activationCodeRepository;
        _activationCodeRecordRepository = activationCodeRecordRepository;
        _logger = logger;
    }

    public async Task<List<ActivationCodeAggregateRoot>> CreateBatchAsync(
        List<(ActivationCodeGoodsTypeEnum GoodsType, int Count)> items)
    {
        var entities = new List<ActivationCodeAggregateRoot>();
        foreach (var item in items)
        {
            if (item.Count <= 0)
            {
                throw new UserFriendlyException("生成数量必须大于0");
            }

            var goods = item.GoodsType.GetGoods();
            if (goods == null)
            {
                throw new UserFriendlyException("激活码商品类型无效");
            }

            for (var i = 0; i < item.Count; i++)
            {
                var code = await GenerateUniqueActivationCodeAsync();
                entities.Add(new ActivationCodeAggregateRoot
                {
                    Code = code,
                    GoodsType = item.GoodsType,
                    IsReusable = goods.IsReusable,
                    IsSameTypeOnce = goods.IsSameTypeOnce,
                    UsedCount = 0,
                    Remark = null
                });
            }
        }

        await _activationCodeRepository.InsertRangeAsync(entities);
        return entities;
    }

    public async Task<ActivationCodeRedeemContext> RedeemAsync(Guid userId, string code)
    {
        if (string.IsNullOrWhiteSpace(code))
        {
            throw new UserFriendlyException("激活码不能为空");
        }

        var trimmedCode = code.Trim();
        var activationCode = await _activationCodeRepository._DbQueryable
            .Where(x => x.Code == trimmedCode)
            .FirstAsync();

        if (activationCode == null)
        {
            throw new UserFriendlyException("激活码不存在");
        }

        var hasUsedCurrentCode = await _activationCodeRecordRepository._DbQueryable
            .Where(x => x.UserId == userId && x.ActivationCodeId == activationCode.Id)
            .AnyAsync();

        if (hasUsedCurrentCode)
        {
            throw new UserFriendlyException("该激活码已被你使用过");
        }

        if (!activationCode.IsReusable && activationCode.UsedCount > 0)
        {
            throw new UserFriendlyException("该激活码已被使用");
        }

        if (activationCode.IsSameTypeOnce)
        {
            var hasUsedSameType = await _activationCodeRecordRepository._DbQueryable
                .Where(x => x.UserId == userId && x.GoodsType == activationCode.GoodsType)
                .AnyAsync();

            if (hasUsedSameType)
            {
                throw new UserFriendlyException("该类型激活码每个用户只能兑换一次");
            }
        }

        var goods = activationCode.GoodsType.GetGoods();
        if (goods == null)
        {
            throw new UserFriendlyException("激活码商品类型无效");
        }

        var packageName = string.IsNullOrWhiteSpace(goods.Content)
            ? goods.DisplayName
            : $"{goods.DisplayName} {goods.Content}";

        activationCode.UsedCount += 1;
        await _activationCodeRepository.UpdateAsync(activationCode);

        var record = new ActivationCodeRecordAggregateRoot
        {
            ActivationCodeId = activationCode.Id,
            Code = activationCode.Code,
            UserId = userId,
            GoodsType = activationCode.GoodsType,
            RedeemTime = DateTime.Now,
            Remark = "激活码兑换"
        };
        await _activationCodeRecordRepository.InsertAsync(record);

        _logger.LogInformation("用户 {UserId} 兑换激活码 {Code} 成功", userId, activationCode.Code);

        return new ActivationCodeRedeemContext
        {
            ActivationCode = activationCode,
            PackageName = packageName,
            Goods = goods
        };
    }

    private async Task<string> GenerateUniqueActivationCodeAsync()
    {
        string code;
        do
        {
            code = GenerateActivationCode();
        } while (await _activationCodeRepository._DbQueryable.AnyAsync(x => x.Code == code));

        return code;
    }

    private string GenerateActivationCode()
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var random = new Random();
        var builder = new StringBuilder(16);
        for (var i = 0; i < 16; i++)
        {
            builder.Append(chars[random.Next(chars.Length)]);
        }

        return builder.ToString();
    }

}
