using Microsoft.EntityFrameworkCore;
using MissionService.Domain.AggregatesModel.MissionAggregate;
using MissionService.Domain.SeedWork;

namespace MissionService.Infrastructure.Repositories;

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

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

    public Mission Add(Mission mission)
    {
        return _context.Missions.Add(mission).Entity;
    }

    public void Update(Mission mission)
    {
        _context.Entry(mission).State = EntityState.Modified;
    }

    public async Task<Mission?> GetByIdAsync(Guid id, CancellationToken ct = default)
    {
        return await _context.Missions
            .Include(m => m.Rules)
            .FirstOrDefaultAsync(m => m.Id == id, ct);
    }

    public async Task<Mission?> GetByCodeAsync(string code, CancellationToken ct = default)
    {
        return await _context.Missions
            .Include(m => m.Rules)
            .FirstOrDefaultAsync(m => m.Code == code, ct);
    }

    public async Task<IReadOnlyList<Mission>> GetActiveMissionsAsync(CancellationToken ct = default)
    {
        return await _context.Missions
            .Include(m => m.Rules)
            .Where(m => m.Status == MissionStatus.Active)
            .Where(m => m.StartDate <= DateTime.UtcNow)
            .Where(m => m.EndDate == null || m.EndDate >= DateTime.UtcNow)
            .OrderByDescending(m => m.Priority)
            .ToListAsync(ct);
    }

    public async Task<IReadOnlyList<Mission>> GetByTypeAsync(MissionType type, CancellationToken ct = default)
    {
        return await _context.Missions
            .Include(m => m.Rules)
            .Where(m => m.Type == type)
            .Where(m => m.Status == MissionStatus.Active)
            .OrderByDescending(m => m.Priority)
            .ToListAsync(ct);
    }

    public async Task<IReadOnlyList<Mission>> GetByCategoryAsync(MissionCategory category, CancellationToken ct = default)
    {
        return await _context.Missions
            .Include(m => m.Rules)
            .Where(m => m.Category == category)
            .Where(m => m.Status == MissionStatus.Active)
            .OrderByDescending(m => m.Priority)
            .ToListAsync(ct);
    }
}
