using MediatR;
using ColaFlow.Modules.ProjectManagement.Application.DTOs;
using ColaFlow.Modules.ProjectManagement.Domain.Repositories;
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
using ColaFlow.Modules.ProjectManagement.Domain.Exceptions;

namespace ColaFlow.Modules.ProjectManagement.Application.Queries.GetTasksByProjectId;

/// <summary>
/// Handler for GetTasksByProjectIdQuery
/// </summary>
public sealed class GetTasksByProjectIdQueryHandler(IProjectRepository projectRepository)
    : IRequestHandler<GetTasksByProjectIdQuery, List<TaskDto>>
{
    private readonly IProjectRepository _projectRepository = projectRepository ?? throw new ArgumentNullException(nameof(projectRepository));

    public async Task<List<TaskDto>> Handle(GetTasksByProjectIdQuery request, CancellationToken cancellationToken)
    {
        // Use read-only method for query (AsNoTracking for better performance)
        var projectId = ProjectId.From(request.ProjectId);
        var project = await _projectRepository.GetProjectWithFullHierarchyReadOnlyAsync(projectId, cancellationToken);

        if (project == null)
            throw new NotFoundException("Project", request.ProjectId);

        // Get all tasks from all stories in all epics
        var allTasks = project.Epics
            .SelectMany(epic => epic.Stories)
            .SelectMany(story => story.Tasks)
            .ToList();

        // Apply filters
        if (!string.IsNullOrWhiteSpace(request.Status))
        {
            allTasks = allTasks.Where(t => t.Status.Name.Equals(request.Status, StringComparison.OrdinalIgnoreCase)).ToList();
        }

        if (request.AssigneeId.HasValue)
        {
            allTasks = allTasks.Where(t => t.AssigneeId != null && t.AssigneeId.Value == request.AssigneeId.Value).ToList();
        }

        // Map to DTOs
        return allTasks.Select(task => new TaskDto
        {
            Id = task.Id.Value,
            Title = task.Title,
            Description = task.Description,
            StoryId = task.StoryId.Value,
            Status = task.Status.Name,
            Priority = task.Priority.Name,
            AssigneeId = task.AssigneeId?.Value,
            EstimatedHours = task.EstimatedHours,
            ActualHours = task.ActualHours,
            CreatedBy = task.CreatedBy.Value,
            CreatedAt = task.CreatedAt,
            UpdatedAt = task.UpdatedAt
        }).ToList();
    }
}
