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.GetStoriesByProjectId;

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

    public async Task<List<StoryDto>> Handle(GetStoriesByProjectIdQuery 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 stories from all epics
        var stories = project.Epics
            .SelectMany(epic => epic.Stories.Select(story => new StoryDto
            {
                Id = story.Id.Value,
                Title = story.Title,
                Description = story.Description,
                EpicId = story.EpicId.Value,
                Status = story.Status.Name,
                Priority = story.Priority.Name,
                AssigneeId = story.AssigneeId?.Value,
                EstimatedHours = story.EstimatedHours,
                ActualHours = story.ActualHours,
                CreatedBy = story.CreatedBy.Value,
                CreatedAt = story.CreatedAt,
                UpdatedAt = story.UpdatedAt,
                Tasks = story.Tasks.Select(t => new TaskDto
                {
                    Id = t.Id.Value,
                    Title = t.Title,
                    Description = t.Description,
                    StoryId = t.StoryId.Value,
                    Status = t.Status.Name,
                    Priority = t.Priority.Name,
                    AssigneeId = t.AssigneeId?.Value,
                    EstimatedHours = t.EstimatedHours,
                    ActualHours = t.ActualHours,
                    CreatedBy = t.CreatedBy.Value,
                    CreatedAt = t.CreatedAt,
                    UpdatedAt = t.UpdatedAt
                }).ToList()
            }))
            .ToList();

        return stories;
    }
}
