using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Services;
using Volo.Abp.Users;
using Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
using Yi.Framework.AiHub.Application.Contracts.IServices;
using Yi.Framework.AiHub.Domain.Entities;
using Yi.Framework.AiHub.Domain.Extensions;
using Yi.Framework.AiHub.Domain.Managers;
using Yi.Framework.SqlSugarCore.Abstractions;

namespace Yi.Framework.AiHub.Application.Services;

/// <summary>
/// 翻牌服务 - 应用层组合服务
/// </summary>
[Authorize]
public class CardFlipService : ApplicationService, ICardFlipService
{
    private readonly CardFlipManager _cardFlipManager;
    private readonly InviteCodeManager _inviteCodeManager;
    private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
    private readonly ILogger<CardFlipService> _logger;

    public CardFlipService(
        CardFlipManager cardFlipManager,
        InviteCodeManager inviteCodeManager,
        ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository,
        ILogger<CardFlipService> logger)
    {
        _cardFlipManager = cardFlipManager;
        _inviteCodeManager = inviteCodeManager;
        _premiumPackageRepository = premiumPackageRepository;
        _logger = logger;
    }

    /// <summary>
    /// 获取本周翻牌任务状态
    /// </summary>
    public async Task<CardFlipStatusOutput> GetWeeklyTaskStatusAsync()
    {
        var userId = CurrentUser.GetId();
        var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);

        // 获取本周任务
        var task = await _cardFlipManager.GetOrCreateWeeklyTaskAsync(userId, weekStart, createIfNotExists: false);

        // 获取邀请码信息
        var inviteCode = await _inviteCodeManager.GetUserInviteCodeAsync(userId);

        // 统计本周邀请人数
        var invitedCount = await _inviteCodeManager.GetWeeklyInvitationCountAsync(userId, weekStart);

        //当前用户是否已填写过邀请码
        var isFilledInviteCode = await _inviteCodeManager.IsFilledInviteCodeAsync(userId);
        var output = new CardFlipStatusOutput
        {
            TotalFlips = task?.TotalFlips ?? 0,
            RemainingFreeFlips = CardFlipManager.MAX_FREE_FLIPS - (task?.FreeFlipsUsed ?? 0),
            RemainingBonusFlips = 0, // 已废弃
            RemainingInviteFlips = CardFlipManager.MAX_INVITE_FLIPS - (task?.InviteFlipsUsed ?? 0),
            CanFlip = _cardFlipManager.CanFlipCard(task),
            MyInviteCode = inviteCode?.Code,
            InvitedCount = invitedCount,
            FlipRecords = BuildFlipRecords(task),
            IsFilledInviteCode = isFilledInviteCode
        };

        // 生成提示信息
        output.NextFlipTip = GenerateNextFlipTip(output);

        return output;
    }

    /// <summary>
    /// 翻牌
    /// </summary>
    public async Task<FlipCardOutput> FlipCardAsync(FlipCardInput input)
    {
        var userId = CurrentUser.GetId();
        var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);

        // 执行翻牌逻辑(由Manager处理验证和翻牌)
        var result = await _cardFlipManager.ExecuteFlipAsync(userId, input.FlipNumber, weekStart);

        // 如果中奖,发放奖励
        if (result.IsWin)
        {
            await GrantRewardAsync(userId, result.RewardAmount, $"翻牌活动-序号{input.FlipNumber}中奖");
        }

        // 构建输出
        var output = new FlipCardOutput
        {
            FlipNumber = result.FlipNumber,
            IsWin = result.IsWin,
            RewardAmount = result.RewardAmount,
            RewardDesc = result.RewardDesc,
            RemainingFlips = CardFlipManager.TOTAL_MAX_FLIPS - input.FlipNumber
        };

        return output;
    }

    /// <summary>
    /// 使用邀请码解锁翻牌次数
    /// </summary>
    public async Task UseInviteCodeAsync(UseInviteCodeInput input)
    {
        var userId = CurrentUser.GetId();
        var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);

        // 获取本周任务
        var task = await _cardFlipManager.GetOrCreateWeeklyTaskAsync(userId, weekStart, createIfNotExists: true);

        // 验证是否已经使用了所有邀请解锁次数
        if (task.InviteFlipsUsed >= CardFlipManager.MAX_INVITE_FLIPS)
        {
            throw new UserFriendlyException("本周邀请解锁次数已用完");
        }

        // 使用邀请码(由Manager处理验证和邀请逻辑)
        await _inviteCodeManager.UseInviteCodeAsync(userId, input.InviteCode);

        _logger.LogInformation($"用户 {userId} 使用邀请码 {input.InviteCode} 解锁翻牌次数成功");
    }

    /// <summary>
    /// 获取我的邀请码信息
    /// </summary>
    public async Task<InviteCodeOutput> GetMyInviteCodeAsync()
    {
        var userId = CurrentUser.GetId();
        var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);

        // 获取我的邀请码
        var inviteCode = await _inviteCodeManager.GetUserInviteCodeAsync(userId);

        // 统计本周邀请人数
        var invitedCount = await _inviteCodeManager.GetWeeklyInvitationCountAsync(userId, weekStart);

        // 获取邀请历史
        var invitationHistory = await _inviteCodeManager.GetInvitationHistoryAsync(userId, 10);

        return new InviteCodeOutput
        {
            MyInviteCode = inviteCode?.Code,
            InvitedCount = invitedCount,
            InvitationHistory = invitationHistory.Select(x => new InvitationHistoryItem
            {
                InvitedUserName = x.InvitedUserName,
                InvitationTime = x.InvitationTime,
                WeekDescription = GetWeekDescription(x.InvitationTime)
            }).ToList()
        };
    }

    /// <summary>
    /// 生成我的邀请码
    /// </summary>
    public async Task<string> GenerateMyInviteCodeAsync()
    {
        var userId = CurrentUser.GetId();

        // 生成邀请码(由Manager处理)
        var code = await _inviteCodeManager.GenerateInviteCodeForUserAsync(userId);

        return code;
    }

    #region 私有辅助方法

    /// <summary>
    /// 构建翻牌记录列表
    /// </summary>
    private List<CardFlipRecord> BuildFlipRecords(CardFlipTaskAggregateRoot? task)
    {
        var records = new List<CardFlipRecord>();

        // 获取已翻牌的顺序
        var flippedOrder = task != null ? _cardFlipManager.GetFlippedOrder(task) : new List<int>();
        var flippedNumbers = new HashSet<int>(flippedOrder);

        // 获取中奖记录
        var winRecords = task?.WinRecords ?? new Dictionary<int, long>();

        // 构建记录，按照原始序号1-10排列
        for (int i = 1; i <= CardFlipManager.TOTAL_MAX_FLIPS; i++)
        {
            var record = new CardFlipRecord
            {
                FlipNumber = i,
                IsFlipped = flippedNumbers.Contains(i),
                IsWin = false,
                FlipTypeDesc = CardFlipManager.GetFlipTypeDesc(i),
                // 设置在翻牌顺序中的位置（0表示未翻，>0表示第几个翻的）
                FlipOrderIndex = flippedOrder.IndexOf(i) >= 0 ? flippedOrder.IndexOf(i) + 1 : 0
            };

            // 设置中奖信息
            // 判断这张卡是第几次翻的
            if (task != null && flippedNumbers.Contains(i))
            {
                var flipOrderIndex = flippedOrder.IndexOf(i) + 1; // 第几次翻的（1-based）

                // 检查这次翻牌是否中奖
                if (winRecords.TryGetValue(flipOrderIndex, out var rewardAmount))
                {
                    record.IsWin = true;
                    record.RewardAmount = rewardAmount;
                }
            }

            records.Add(record);
        }

        return records;
    }

    /// <summary>
    /// 生成下次翻牌提示
    /// </summary>
    private string GenerateNextFlipTip(CardFlipStatusOutput status)
    {
        if (status.TotalFlips >= CardFlipManager.TOTAL_MAX_FLIPS)
        {
            return "本周翻牌次数已用完,请下周再来!";
        }

        if (status.RemainingFreeFlips > 0)
        {
            return $"本周您还有{status.RemainingFreeFlips}次免费翻牌机会";
        }
        else if (status.RemainingInviteFlips > 0)
        {
            if (status.TotalFlips >= 7)
            {
                return $"本周使用他人邀请码或他人使用你的邀请码，可解锁{status.RemainingInviteFlips}次翻牌，且必中大奖!每次中奖最大额度将翻倍!";
            }

            return $"本周使用他人邀请码或他人使用你的邀请码，可解锁{status.RemainingInviteFlips}次翻牌，必中大奖!每次中奖最大额度将翻倍!";
        }

        return "继续加油!";
    }

    /// <summary>
    /// 发放奖励
    /// </summary>
    private async Task GrantRewardAsync(Guid userId, long amount, string description)
    {
        var premiumPackage = new PremiumPackageAggregateRoot(userId, amount, description)
        {
            PurchaseAmount = 0, // 奖励不需要付费
            Remark = $"翻牌活动奖励:{amount / 10000}w tokens"
        };

        await _premiumPackageRepository.InsertAsync(premiumPackage);

        _logger.LogInformation($"用户 {userId} 获得翻牌奖励 {amount / 10000}w tokens");
    }

    /// <summary>
    /// 获取周描述
    /// </summary>
    private string GetWeekDescription(DateTime date)
    {
        var weekStart = CardFlipManager.GetWeekStartDate(date);
        var weekEnd = weekStart.AddDays(6);

        return $"{weekStart:MM-dd} 至 {weekEnd:MM-dd}";
    }

    #endregion
}