using Microsoft.EntityFrameworkCore;
using MissionService.Domain.AggregatesModel.TaskAggregate;
using MissionService.Domain.SeedWork;
using TaskStatus = MissionService.Domain.AggregatesModel.TaskAggregate.TaskStatus;

namespace MissionService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for UserTask aggregate
/// VI: Triển khai repository cho UserTask aggregate
/// </summary>
public class UserTaskRepository : IUserTaskRepository
{
    private readonly MissionDbContext _context;
    
    public IUnitOfWork UnitOfWork => _context;

    public UserTaskRepository(MissionDbContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public UserTask Add(UserTask task)
    {
        return _context.UserTasks.Add(task).Entity;
    }

    public void Update(UserTask task)
    {
        _context.Entry(task).State = EntityState.Modified;
    }

    public async Task<UserTask?> GetByIdAsync(Guid id, CancellationToken ct = default)
    {
        return await _context.UserTasks.FindAsync(new object[] { id }, ct);
    }

    public async Task<IReadOnlyList<UserTask>> GetByUserIdAsync(Guid userId, CancellationToken ct = default)
    {
        return await _context.UserTasks
            .Where(t => t.UserId == userId)
            .OrderByDescending(t => t.StartedAt)
            .ToListAsync(ct);
    }

    public async Task<IReadOnlyList<UserTask>> GetActiveByUserIdAsync(Guid userId, CancellationToken ct = default)
    {
        return await _context.UserTasks
            .Where(t => t.UserId == userId)
            .Where(t => t.Status == TaskStatus.InProgress || t.Status == TaskStatus.PendingVerification)
            .OrderByDescending(t => t.StartedAt)
            .ToListAsync(ct);
    }

    public async Task<UserTask?> GetByUserAndMissionAsync(Guid userId, Guid missionId, CancellationToken ct = default)
    {
        return await _context.UserTasks
            .Where(t => t.UserId == userId && t.MissionId == missionId)
            .Where(t => t.Status == TaskStatus.InProgress || t.Status == TaskStatus.PendingVerification)
            .FirstOrDefaultAsync(ct);
    }

    public async Task<IReadOnlyList<UserTask>> GetCompletedByUserAsync(
        Guid userId, 
        DateTime fromDate, 
        DateTime toDate, 
        CancellationToken ct = default)
    {
        return await _context.UserTasks
            .Where(t => t.UserId == userId)
            .Where(t => t.Status == TaskStatus.Completed)
            .Where(t => t.CompletedAt >= fromDate && t.CompletedAt <= toDate)
            .OrderByDescending(t => t.CompletedAt)
            .ToListAsync(ct);
    }

    public async Task<int> CountCompletionsByUserAndMissionAsync(
        Guid userId, 
        Guid missionId, 
        CancellationToken ct = default)
    {
        return await _context.UserTasks
            .CountAsync(t => t.UserId == userId 
                && t.MissionId == missionId 
                && t.Status == TaskStatus.Completed, ct);
    }

    public async Task<IReadOnlyList<UserTask>> GetPendingVerificationAsync(CancellationToken ct = default)
    {
        return await _context.UserTasks
            .Where(t => t.Status == TaskStatus.PendingVerification)
            .OrderBy(t => t.StartedAt)
            .ToListAsync(ct);
    }
}
