using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using NPP.SmartSchedue.Api.Contracts.Core.Repositories;
using NPP.SmartSchedue.Api.Contracts.Domain.Notification;
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
using NPP.SmartSchedue.Api.Core.Repositories;
using ZhonTai.Admin.Core.Db.Transaction;

namespace NPP.SmartSchedue.Api.Repositories.Notification;

/// <summary>
/// 通知任务仓储实现
/// 决策点6：定时任务，支持定时检查和触发通知
/// 业务思考：
/// 1. 支持一次性任务和周期性任务（Cron表达式）
/// 2. 任务状态管理（待执行、执行中、已完成、失败、取消）
/// 3. 任务重试机制和失效时间控制
/// 4. 任务执行结果记录和错误处理
/// </summary>
public class NotificationTaskRepository : AppRepositoryBase<NotificationTaskEntity>, INotificationTaskRepository
{
    public NotificationTaskRepository(UnitOfWorkManagerCloud uowm) : base(uowm)
    {
    }

    /// <summary>
    /// 根据通知设置ID获取任务列表
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetByNotificationSettingIdAsync(long notificationSettingId)
    {
        return await Select
            .Where(t => t.NotificationSettingId == notificationSettingId)
            .Include(t => t.NotificationSetting)
            .OrderByDescending(t => t.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 根据任务状态获取任务列表
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetByTaskStatusAsync(NotificationStatusEnum taskStatus)
    {
        return await Select
            .Where(t => t.TaskStatus == (int)taskStatus)
            .Include(t => t.NotificationSetting)
            .OrderByDescending(t => t.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 根据启用状态获取任务列表
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetByEnabledAsync(bool enabled)
    {
        return await Select
            .Where(t => t.IsEnabled == enabled)
            .Include(t => t.NotificationSetting)
            .OrderByDescending(t => t.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 根据业务类型和业务ID获取任务列表
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetByBusinessAsync(string businessType, long? businessId = null)
    {
        var query = Select.Where(t => t.BusinessType == businessType);
        
        if (businessId.HasValue)
            query = query.Where(t => t.BusinessId == businessId.Value);
            
        return await query
            .Include(t => t.NotificationSetting)
            .OrderByDescending(t => t.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 获取待执行的任务列表
    /// 业务逻辑：查询计划执行时间已到达且任务状态为待执行的任务
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetPendingTasksAsync(DateTime currentTime)
    {
        return await Select
            .Where(t => t.IsEnabled == true)
            .Where(t => t.TaskStatus == (int)NotificationStatusEnum.Pending)
            .Where(t => t.PlannedExecutionTime <= currentTime)
            .Where(t => t.ExpirationTime == null || t.ExpirationTime > currentTime) // 排除已过期的任务
            .Include(t => t.NotificationSetting)
            .OrderBy(t => t.PlannedExecutionTime) // 按计划时间升序排序
            .ToListAsync();
    }

    /// <summary>
    /// 获取需要执行的定时任务列表（基于Cron表达式）
    /// 业务逻辑：
    /// 1. 查询启用的周期性任务
    /// 2. 检查下次执行时间是否已到达
    /// 3. 验证任务未过期且未达到最大执行次数
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetCronTasksForExecutionAsync(DateTime currentTime)
    {
        return await Select
            .Where(t => t.IsEnabled == true)
            .Where(t => !string.IsNullOrWhiteSpace(t.CronExpression)) // 有Cron表达式的周期性任务
            .Where(t => t.TaskStatus != (int)NotificationStatusEnum.Cancelled)
            .Where(t => t.NextExecutionTime <= currentTime) // 下次执行时间已到
            .Where(t => t.ExpirationTime == null || t.ExpirationTime > currentTime) // 未过期
            .Where(t => t.MaxExecutionCount == null || t.ExecutionCount < t.MaxExecutionCount) // 未达到最大执行次数
            .Include(t => t.NotificationSetting)
            .OrderBy(t => t.NextExecutionTime)
            .ToListAsync();
    }

    /// <summary>
    /// 更新任务执行状态
    /// 业务逻辑：更新任务状态、执行结果、错误信息等
    /// </summary>
    public async Task UpdateExecutionStatusAsync(long taskId, NotificationStatusEnum taskStatus, string executionResult = "", string errorMessage = "")
    {
        var currentTime = DateTime.Now;
        
        await UpdateDiy
            .Set(t => t.TaskStatus, (int)taskStatus)
            .Set(t => t.LastExecutionTime, currentTime)
            .SetIf(!string.IsNullOrWhiteSpace(executionResult), t => t.ExecutionResult, executionResult)
            .SetIf(!string.IsNullOrWhiteSpace(errorMessage), t => t.ErrorMessage, errorMessage)
            .Set(t => t.ModifiedTime, currentTime)
            .Where(t => t.Id == taskId)
            .ExecuteAffrowsAsync();
    }

    /// <summary>
    /// 更新任务下次执行时间
    /// 业务场景：周期性任务完成后，根据Cron表达式计算下次执行时间
    /// </summary>
    public async Task UpdateNextExecutionTimeAsync(long taskId, DateTime? nextExecutionTime)
    {
        await UpdateDiy
            .Set(t => t.NextExecutionTime, nextExecutionTime)
            .Set(t => t.ModifiedTime, DateTime.Now)
            .Where(t => t.Id == taskId)
            .ExecuteAffrowsAsync();
    }

    /// <summary>
    /// 增加任务执行次数
    /// 业务逻辑：记录任务执行统计，用于控制最大执行次数和成功率分析
    /// </summary>
    public async Task IncrementExecutionCountAsync(long taskId, bool isSuccess)
    {
        var task = await Select.Where(t => t.Id == taskId).FirstAsync();
        if (task == null) return;

        await UpdateDiy
            .Set(t => t.ExecutionCount, task.ExecutionCount + 1)
            .SetIf(isSuccess, t => t.SuccessCount, task.SuccessCount + 1)
            .SetIf(!isSuccess, t => t.FailureCount, task.FailureCount + 1)
            .Set(t => t.ModifiedTime, DateTime.Now)
            .Where(t => t.Id == taskId)
            .ExecuteAffrowsAsync();
    }

    /// <summary>
    /// 检查任务是否应该停止执行
    /// 业务规则：
    /// 1. 任务被禁用
    /// 2. 任务已取消
    /// 3. 已达到最大执行次数
    /// 4. 任务已过期
    /// 5. 连续失败次数过多
    /// </summary>
    public async Task<bool> ShouldStopExecutionAsync(long taskId)
    {
        var task = await Select.Where(t => t.Id == taskId).FirstAsync();
        if (task == null) return true;

        var currentTime = DateTime.Now;

        // 检查基本停止条件
        if (!task.IsEnabled || 
            task.TaskStatus == (int)NotificationStatusEnum.Cancelled ||
            (task.ExpirationTime.HasValue && task.ExpirationTime.Value <= currentTime) ||
            (task.MaxExecutionCount.HasValue && task.ExecutionCount >= task.MaxExecutionCount.Value))
        {
            return true;
        }

        // 检查连续失败次数（如果设置了最大重试次数）
        if (task.MaxRetryCount.HasValue && task.FailureCount >= task.MaxRetryCount.Value)
        {
            return true;
        }

        return false;
    }

    /// <summary>
    /// 获取过期的任务列表
    /// 业务场景：定期清理过期任务，释放系统资源
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetExpiredTasksAsync(DateTime expiredBefore)
    {
        return await Select
            .Where(t => t.ExpirationTime <= expiredBefore)
            .Where(t => t.TaskStatus != (int)NotificationStatusEnum.Cancelled) // 排除已取消的任务
            .OrderBy(t => t.ExpirationTime)
            .ToListAsync();
    }

    /// <summary>
    /// 清理过期的任务
    /// 业务逻辑：将过期任务状态设为已取消，而不是物理删除，保留审计记录
    /// </summary>
    public async Task<int> CleanupExpiredTasksAsync(DateTime expiredBefore)
    {
        var currentTime = DateTime.Now;
        
        var affectedRows = await UpdateDiy
            .Set(t => t.TaskStatus, (int)NotificationStatusEnum.Cancelled)
            .Set(t => t.ErrorMessage, "任务已过期自动取消")
            .Set(t => t.ModifiedTime, currentTime)
            .Where(t => t.ExpirationTime <= expiredBefore)
            .Where(t => t.TaskStatus != (int)NotificationStatusEnum.Cancelled)
            .ExecuteAffrowsAsync();

        return (int)affectedRows;
    }

    /// <summary>
    /// 获取需要重试的失败任务列表
    /// 业务场景：定时重试失败的任务，提高通知送达率
    /// </summary>
    public async Task<List<NotificationTaskEntity>> GetFailedTasksForRetryAsync()
    {
        var currentTime = DateTime.Now;
        
        return await Select
            .Where(t => t.TaskStatus == (int)NotificationStatusEnum.Failed)
            .Where(t => t.IsEnabled == true)
            .Where(t => t.NextRetryTime <= currentTime) // 重试时间已到
            .Where(t => t.MaxRetryCount == null || t.RetryCount < t.MaxRetryCount) // 未达到最大重试次数
            .Where(t => t.ExpirationTime == null || t.ExpirationTime > currentTime) // 未过期
            .Include(t => t.NotificationSetting)
            .OrderBy(t => t.NextRetryTime)
            .ToListAsync();
    }

    /// <summary>
    /// 更新任务重试信息
    /// 业务逻辑：更新重试次数和下次重试时间
    /// </summary>
    public async Task UpdateRetryInfoAsync(long taskId, int retryCount, DateTime? nextRetryTime)
    {
        await UpdateDiy
            .Set(t => t.RetryCount, retryCount)
            .Set(t => t.NextRetryTime, nextRetryTime)
            .Set(t => t.ModifiedTime, DateTime.Now)
            .Where(t => t.Id == taskId)
            .ExecuteAffrowsAsync();
    }

    /// <summary>
    /// 批量更新任务状态
    /// 业务场景：批量操作，提高性能
    /// </summary>
    public async Task<int> BatchUpdateTaskStatusAsync(List<long> taskIds, NotificationStatusEnum status, string reason = "")
    {
        if (!taskIds.Any()) return 0;

        var currentTime = DateTime.Now;
        
        var affectedRows = await UpdateDiy
            .Set(t => t.TaskStatus, (int)status)
            .SetIf(!string.IsNullOrWhiteSpace(reason), t => t.ErrorMessage, reason)
            .Set(t => t.ModifiedTime, currentTime)
            .Where(t => taskIds.Contains(t.Id))
            .ExecuteAffrowsAsync();

        return (int)affectedRows;
    }
}