using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Dto.Compensation;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.Repository;
using SqlSugar;

namespace QYZH.InteractiveMagazine.Service;

/// <summary>
/// 补偿任务管理服务实现
/// </summary>
public class CompensationManageService(
    BaseRepository<CompensationTask> compensationTaskRepository,
    IOperationLogService operationLogService,
    ILogger<CompensationManageService> logger)
    : BaseRepository<CompensationTask>, ICompensationManageService
{
    /// <summary>
    /// 分页查询补偿任务（含用户昵称）
    /// </summary>
    public async Task<PageListModel<CompensationManageOutput>> GetListAsync(CompensationTaskQueryInput input)
    {
        if (input.PageIndex <= 0)
            input.PageIndex = 1;

        if (input.PageSize <= 0 || input.PageSize > 100)
            input.PageSize = 10;

        RefAsync<int> totalNumber = 0;

        var pageResult = await compensationTaskRepository.Queryable()
            .LeftJoin<Users>((t, u) => t.UserId == u.Id)
            .WhereIF(input.UserId.HasValue, (t, u) => t.UserId == input.UserId.Value)
            .WhereIF(input.TaskType.HasValue, (t, u) => t.TaskType == (int)input.TaskType.Value)
            .WhereIF(input.Status.HasValue, (t, u) => t.Status == (int)input.Status)
            .WhereIF(!string.IsNullOrWhiteSpace(input.BusinessSource), (t, u) => t.BusinessSource == input.BusinessSource)
            .OrderByDescending((t, u) => t.CreatedAt)
            .Select((t, u) => new CompensationManageOutput
            {
                Id = t.Id,
                TaskType = (CompensationTaskTypeEnum)t.TaskType,
                BusinessSource = t.BusinessSource,
                BusinessId = t.BusinessId,
                UserId = t.UserId,
                UserName = u.Name,
                Payload = t.Payload,
                ErrorMessage = t.ErrorMessage,
                ErrorSource = t.ErrorSource,
                RetryCount = t.RetryCount,
                MaxRetries = t.MaxRetries,
                Status = (CompensationTaskStatusEnum)t.Status,
                ProcessedAt = t.ProcessedAt,
                ScheduledAt = t.ScheduledAt,
                ResultMessage = t.ResultMessage,
                CreatedAt = t.CreatedAt
            })
            .ToPageListAsync(input.PageIndex, input.PageSize, totalNumber);

        return new PageListModel<CompensationManageOutput>(pageResult, input.PageIndex, input.PageSize, totalNumber);
    }

    /// <summary>
    /// 手动重试补偿任务
    /// </summary>
    public async Task RetryAsync(long taskId, long operatorId, string operatorName, CompensationRetryInput input, string? ipAddress = null)
    {
        logger.LogInformation("手动重试补偿任务，TaskId: {TaskId}, Operator: {Operator}", taskId, operatorName);

        var task = await compensationTaskRepository.GetByIdAsync(taskId);
        if (task == null)
            throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND);

        if (task.Status != (int)CompensationTaskStatusEnum.Failed && task.Status != (int)CompensationTaskStatusEnum.Cancelled)
            throw new BusinessException($"只有失败或已取消的任务才能重试，当前状态: {task.Status}", ResultCode.BAD_REQUEST);

        // 重置任务状态为 Pending，清零重试次数，设置立即执行
        await compensationTaskRepository.Context.Updateable<CompensationTask>()
            .SetColumns(t => t.Status == (int)CompensationTaskStatusEnum.Pending)
            .SetColumns(t => t.RetryCount == 0)
            .SetColumns(t => t.ScheduledAt == DateTime.Now)
            .SetColumns(t => t.ResultMessage == $"管理员手动重试: {input.Reason}")
            .SetColumns(t => t.UpdatedBy == operatorName)
            .SetColumns(t => t.UpdatedAt == DateTime.Now)
            .Where(t => t.Id == taskId && !t.IsDeleted)
            .ExecuteCommandAsync();

        // 记录操作日志
        var detail = JsonConvert.SerializeObject(new
        {
            OriginalStatus = task.Status,
            Reason = input.Reason,
            TaskType = task.TaskType,
            UserId = task.UserId
        });

        await operationLogService.LogAsync(
            operatorId, operatorName,
            OperationLogActionType.CompensationRetry,
            OperationLogTargetType.CompensationTask,
            taskId, null, detail, ipAddress);

        logger.LogInformation("补偿任务手动重试成功，TaskId: {TaskId}", taskId);
    }

    /// <summary>
    /// 标记补偿任务为已解决
    /// </summary>
    public async Task ResolveAsync(long taskId, long operatorId, string operatorName, CompensationResolveInput input, string? ipAddress = null)
    {
        logger.LogInformation("标记补偿任务已解决，TaskId: {TaskId}, Operator: {Operator}", taskId, operatorName);

        var task = await compensationTaskRepository.GetByIdAsync(taskId);
        if (task == null)
            throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND);

        if (task.Status == (int)CompensationTaskStatusEnum.Success)
            throw new BusinessException("该任务已经是成功状态，无需标记", ResultCode.BAD_REQUEST);

        // 标记为 Success
        await compensationTaskRepository.Context.Updateable<CompensationTask>()
            .SetColumns(t => t.Status == (int)CompensationTaskStatusEnum.Success)
            .SetColumns(t => t.ResultMessage == $"管理员手动标记已解决: {input.ResolveNote}")
            .SetColumns(t => t.ProcessedAt == DateTime.Now)
            .SetColumns(t => t.UpdatedBy == operatorName)
            .SetColumns(t => t.UpdatedAt == DateTime.Now)
            .Where(t => t.Id == taskId && !t.IsDeleted)
            .ExecuteCommandAsync();

        // 记录操作日志
        var detail = JsonConvert.SerializeObject(new
        {
            OriginalStatus = task.Status,
            ResolveNote = input.ResolveNote,
            TaskType = task.TaskType,
            UserId = task.UserId
        });

        await operationLogService.LogAsync(
            operatorId, operatorName,
            OperationLogActionType.CompensationResolve,
            OperationLogTargetType.CompensationTask,
            taskId, null, detail, ipAddress);

        logger.LogInformation("补偿任务标记已解决成功，TaskId: {TaskId}", taskId);
    }

    /// <summary>
    /// 获取补偿任务详情
    /// </summary>
    public async Task<CompensationManageDetailOutput> GetDetailAsync(long taskId)
    {
        logger.LogInformation("获取补偿任务详情，TaskId: {TaskId}", taskId);

        var result = await compensationTaskRepository.Queryable()
            .LeftJoin<Users>((t, u) => t.UserId == u.Id)
            .Where((t, u) => t.Id == taskId && !t.IsDeleted)
            .Select((t, u) => new CompensationManageDetailOutput
            {
                Id = t.Id,
                TaskType = (CompensationTaskTypeEnum)t.TaskType,
                BusinessSource = t.BusinessSource,
                BusinessId = t.BusinessId,
                UserId = t.UserId,
                UserName = u.Name,
                Payload = t.Payload,
                ErrorMessage = t.ErrorMessage,
                ErrorSource = t.ErrorSource,
                RetryCount = t.RetryCount,
                MaxRetries = t.MaxRetries,
                Status = (CompensationTaskStatusEnum)t.Status,
                ProcessedAt = t.ProcessedAt,
                ScheduledAt = t.ScheduledAt,
                ResultMessage = t.ResultMessage,
                CreatedAt = t.CreatedAt,
                CreatedBy = t.CreatedBy,
                UpdatedBy = t.UpdatedBy,
                UpdatedAt = t.UpdatedAt
            })
            .FirstAsync();

        if (result == null)
            throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND);

        return result;
    }
}
