using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Task;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Core.Services;

/// <summary>
/// 任务服务实现
/// </summary>
public class TaskService : ITaskService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly ILogger<TaskService> _logger;

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

    /// <inheritdoc />
    public async Task<TaskListResponse> GetTaskListAsync(int userId, int type)
    {
        // 获取任务列表
        var tasks = await _dbContext.Tasks
            .Where(t => t.Type == type && t.DeletedAt == null)
            .OrderByDescending(t => t.Sort)
            .ThenByDescending(t => t.Id)
            .ToListAsync();

        var taskDtos = new List<TaskDto>();

        foreach (var task in tasks)
        {
            // 计算任务周期时间范围
            var (startTime, endTime) = GetTaskPeriod(task.Type);

            // 计算任务进度
            int completedCount = await CalculateTaskProgress(userId, task.Cate, startTime);

            // 判断是否已完成
            int targetNumber = task.Number ?? 0;
            int isComplete;
            int percentage;
            int ywcCount;

            if (completedCount >= targetNumber)
            {
                isComplete = 1;
                percentage = 100;
                ywcCount = targetNumber;
            }
            else
            {
                isComplete = 0;
                percentage = targetNumber > 0 ? (int)Math.Round((double)completedCount / targetNumber * 100) : 0;
                ywcCount = completedCount;
            }

            // 检查是否已领取
            var hasClaimed = await _dbContext.UserTasks
                .AnyAsync(ut => ut.UserId == userId 
                    && ut.TaskId == task.Id 
                    && ut.CreatedAt >= startTime 
                    && ut.CreatedAt <= endTime 
                    && ut.DeletedAt == null);

            if (hasClaimed)
            {
                isComplete = 2; // 已领取
            }

            taskDtos.Add(new TaskDto
            {
                Id = task.Id,
                Type = task.Type,
                Cate = task.Cate,
                Title = task.Title,
                Number = targetNumber,
                ZNumber = task.ZNumber ?? 0,
                IsComplete = isComplete,
                Percentage = percentage,
                YwcCount = ywcCount
            });
        }

        return new TaskListResponse
        {
            TaskList = taskDtos
        };
    }

    /// <inheritdoc />
    public async Task<ClaimTaskRewardResponse> ClaimTaskRewardAsync(int userId, int taskListId)
    {
        // 获取任务信息
        var task = await _dbContext.Tasks
            .FirstOrDefaultAsync(t => t.Id == taskListId && t.DeletedAt == null);

        if (task == null)
        {
            throw new InvalidOperationException("任务不存在");
        }

        // 计算任务周期时间范围
        var (startTime, endTime) = GetTaskPeriod(task.Type);

        // 检查任务是否已完成
        int completedCount = await CalculateTaskProgress(userId, task.Cate, startTime);
        int targetNumber = task.Number ?? 0;

        if (completedCount < targetNumber)
        {
            throw new InvalidOperationException("任务未完成");
        }

        // 检查是否已领取
        var hasClaimed = await _dbContext.UserTasks
            .AnyAsync(ut => ut.UserId == userId 
                && ut.TaskId == taskListId 
                && ut.CreatedAt >= startTime 
                && ut.CreatedAt <= endTime 
                && ut.DeletedAt == null);

        if (hasClaimed)
        {
            throw new InvalidOperationException("你已经领取过了");
        }

        // 开始事务
        using var transaction = await _dbContext.Database.BeginTransactionAsync();
        try
        {
            var now = DateTime.Now;

            // 创建用户任务记录
            var userTask = new UserTask
            {
                UserId = userId,
                TaskId = taskListId,
                Type = task.Type,
                Cate = task.Cate,
                IsImportant = task.IsImportant,
                Number = task.Number,
                ZNumber = task.ZNumber,
                CreatedAt = now,
                UpdatedAt = now
            };

            await _dbContext.UserTasks.AddAsync(userTask);

            // 发放欧气值奖励
            int reward = task.ZNumber ?? 0;
            int currentOuQi = 0;

            if (reward > 0)
            {
                var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
                if (user != null)
                {
                    user.OuQi = (user.OuQi ?? 0) + reward;
                    currentOuQi = user.OuQi ?? 0;
                    
                    // 重新计算欧气等级
                    user.OuQiLevel = await CalculateOuQiLevelAsync(currentOuQi);
                    user.UpdatedAt = now;

                    // 记录欧气值变动
                    var profitOuQi = new ProfitOuQi
                    {
                        UserId = userId,
                        ChangeMoney = reward,
                        Money = currentOuQi,
                        Type = 1, // 完成任务
                        Content = "完成任务",
                        CreatedAt = now
                    };

                    await _dbContext.ProfitOuQis.AddAsync(profitOuQi);
                }
            }

            await _dbContext.SaveChangesAsync();
            await transaction.CommitAsync();

            _logger.LogInformation("用户 {UserId} 领取任务 {TaskId} 奖励 {Reward} 欧气值", userId, taskListId, reward);

            return new ClaimTaskRewardResponse
            {
                Reward = reward,
                CurrentOuQi = currentOuQi
            };
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "用户 {UserId} 领取任务 {TaskId} 奖励失败", userId, taskListId);
            throw new InvalidOperationException("网络故障, 请稍后再试");
        }
    }

    /// <summary>
    /// 获取任务周期时间范围
    /// </summary>
    /// <param name="taskType">任务类型: 1=每日, 2=每周</param>
    /// <returns>开始时间和结束时间</returns>
    private (DateTime startTime, DateTime endTime) GetTaskPeriod(int taskType)
    {
        var now = DateTime.Now;

        if (taskType == 1)
        {
            // 每日任务: 当天 00:00:00 到 23:59:59
            var startTime = now.Date;
            var endTime = now.Date.AddDays(1).AddSeconds(-1);
            return (startTime, endTime);
        }
        else
        {
            // 每周任务: 本周一 00:00:00 到 本周日 23:59:59
            var dayOfWeek = (int)now.DayOfWeek;
            // 周日是0，需要转换为7
            if (dayOfWeek == 0) dayOfWeek = 7;
            
            var startTime = now.Date.AddDays(-(dayOfWeek - 1)); // 本周一
            var endTime = startTime.AddDays(7).AddSeconds(-1); // 本周日 23:59:59
            return (startTime, endTime);
        }
    }

    /// <summary>
    /// 计算任务进度
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="taskCate">任务分类: 1=邀请, 2=抽赏</param>
    /// <param name="startTime">开始时间</param>
    /// <returns>完成数量</returns>
    private async Task<int> CalculateTaskProgress(int userId, int taskCate, DateTime startTime)
    {
        if (taskCate == 1)
        {
            // 邀请好友注册: 统计推荐人为当前用户且注册时间在周期内的用户数
            return await _dbContext.Users
                .CountAsync(u => u.Pid == userId && u.CreatedAt >= startTime);
        }
        else if (taskCate == 2)
        {
            // 抽赏任务: 统计已支付订单数 (pay_type < 10 且 status = 1)
            // 将DateTime转换为Unix时间戳进行比较
            var startTimestamp = (int)((DateTimeOffset)startTime).ToUnixTimeSeconds();
            return await _dbContext.Orders
                .CountAsync(o => o.UserId == userId 
                    && o.PayType < 10 
                    && o.Status == 1 
                    && o.Addtime >= startTimestamp);
        }

        return 0;
    }

    /// <summary>
    /// 根据欧气值计算欧气等级
    /// </summary>
    /// <param name="ouQi">当前欧气值</param>
    /// <returns>欧气等级</returns>
    private async Task<int> CalculateOuQiLevelAsync(int ouQi)
    {
        // 从数据库读取等级配置
        var equityLevels = await _dbContext.EquityLevels
            .Where(e => e.DeletedAt == null)
            .OrderByDescending(e => e.Number)
            .ToListAsync();

        if (equityLevels.Any())
        {
            foreach (var level in equityLevels)
            {
                if (ouQi >= level.Number)
                {
                    return level.Level;
                }
            }
            return 0;
        }

        // 如果数据库没有配置，使用默认值
        // 等级阈值: 0=普通, 1=青铜(100), 2=白银(500), 3=黄金(1000), 
        // 4=铂金(3000), 5=钻石(6000), 6=星耀(10000), 7=王者(20000)
        if (ouQi >= 20000) return 7;
        if (ouQi >= 10000) return 6;
        if (ouQi >= 6000) return 5;
        if (ouQi >= 3000) return 4;
        if (ouQi >= 1000) return 3;
        if (ouQi >= 500) return 2;
        if (ouQi >= 100) return 1;
        return 0;
    }
}
