using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
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>
/// 通知历史记录仓储实现
/// </summary>
public class NotificationHistoryRepository : AppRepositoryBase<NotificationHistoryEntity>, INotificationHistoryRepository
{
    public NotificationHistoryRepository(UnitOfWorkManagerCloud uowm) : base(uowm)
    {
    }

    /// <summary>
    /// 根据通知设置ID获取历史记录列表
    /// </summary>
    public async Task<List<NotificationHistoryEntity>> GetByNotificationSettingIdAsync(long notificationSettingId)
    {
        return await Select
            .Where(n => n.NotificationSettingId == notificationSettingId)
            .Include(n => n.NotificationSetting)
            .OrderByDescending(n => n.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 根据接收人员ID获取历史记录列表
    /// </summary>
    public async Task<List<NotificationHistoryEntity>> GetByRecipientPersonnelIdAsync(long recipientPersonnelId)
    {
        return await Select
            .Where(n => n.RecipientPersonnelId == recipientPersonnelId)
            .Include(n => n.NotificationSetting)
            .OrderByDescending(n => n.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 根据发送状态获取历史记录列表
    /// </summary>
    public async Task<List<NotificationHistoryEntity>> GetBySendStatusAsync(NotificationStatusEnum sendStatus)
    {
        return await Select
            .Where(n => n.SendStatus == (int)sendStatus)
            .Include(n => n.NotificationSetting)
            .OrderByDescending(n => n.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 根据通知方式获取历史记录列表
    /// </summary>
    public async Task<List<NotificationHistoryEntity>> GetByNotificationTypeAsync(NotificationTypeEnum notificationType)
    {
        return await Select
            .Where(n => n.NotificationType == (int)notificationType)
            .Include(n => n.NotificationSetting)
            .OrderByDescending(n => n.CreatedTime)
            .ToListAsync();
    }

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

    /// <summary>
    /// 获取需要重试的失败通知列表
    /// </summary>
    public async Task<List<NotificationHistoryEntity>> GetFailedNotificationsForRetryAsync(int? maxRetryCount = null)
    {
        var query = Select
            .Where(n => n.SendStatus == (int)NotificationStatusEnum.Failed)
            .Where(n => n.NextRetryTime <= DateTime.Now)
            .Where(n => n.RetryCount < n.MaxRetryCount);

        if (maxRetryCount.HasValue)
            query = query.Where(n => n.MaxRetryCount <= maxRetryCount.Value);

        return await query
            .Include(n => n.NotificationSetting)
            .OrderBy(n => n.NextRetryTime)
            .ToListAsync();
    }

    /// <summary>
    /// 获取指定时间范围内的通知统计信息
    /// </summary>
    public async Task<Dictionary<string, int>> GetNotificationStatisticsAsync(
        DateTime startTime,
        DateTime endTime,
        long? notificationSettingId = null)
    {
        var query = Select
            .Where(n => n.CreatedTime >= startTime && n.CreatedTime <= endTime);

        if (notificationSettingId.HasValue)
            query = query.Where(n => n.NotificationSettingId == notificationSettingId.Value);

        var histories = await query.ToListAsync();

        var statistics = new Dictionary<string, int>
        {
            ["Total"] = histories.Count,
            ["Success"] = histories.Count(h => h.SendStatus == (int)NotificationStatusEnum.Success),
            ["Failed"] = histories.Count(h => h.SendStatus == (int)NotificationStatusEnum.Failed),
            ["Pending"] = histories.Count(h => h.SendStatus == (int)NotificationStatusEnum.Pending),
            ["Cancelled"] = histories.Count(h => h.SendStatus == (int)NotificationStatusEnum.Cancelled),
            ["Email"] = histories.Count(h => h.NotificationType == (int)NotificationTypeEnum.Email),
            ["SystemMessage"] = histories.Count(h => h.NotificationType == (int)NotificationTypeEnum.SystemMessage)
        };

        return statistics;
    }

    /// <summary>
    /// 根据日期范围获取历史记录列表
    /// </summary>
    public async Task<List<NotificationHistoryEntity>> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
    {
        return await Select
            .Where(n => n.CreatedTime >= startDate && n.CreatedTime <= endDate)
            .Include(n => n.NotificationSetting)
            .OrderByDescending(n => n.CreatedTime)
            .ToListAsync();
    }

    /// <summary>
    /// 更新通知发送状态
    /// </summary>
    public async Task UpdateSendStatusAsync(long id, NotificationStatusEnum sendStatus, string sendResult = "", string errorMessage = "")
    {
        await UpdateDiy
            .SetIf(!string.IsNullOrWhiteSpace(sendResult), n => n.SendResult, sendResult)
            .SetIf(!string.IsNullOrWhiteSpace(errorMessage), n => n.ErrorMessage, errorMessage)
            .Set(n => n.SendStatus, (int)sendStatus)
            .Set(n => n.ActualSendTime, sendStatus == NotificationStatusEnum.Success ? DateTime.Now : (DateTime?)null)
            .Set(n => n.ModifiedTime, DateTime.Now)
            .Where(n => n.Id == id)
            .ExecuteAffrowsAsync();
    }

    /// <summary>
    /// 批量更新通知发送状态
    /// </summary>
    public async Task BatchUpdateSendStatusAsync(List<(long Id, NotificationStatusEnum Status, string Result, string Error)> updates)
    {
        if (!updates.Any()) return;

        // 使用FreeSql的批量更新来提高性能
        foreach (var update in updates)
        {
            await UpdateSendStatusAsync(update.Id, update.Status, update.Result, update.Error);
        }
    }
}