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;
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;

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

/// <summary>
/// Handler for GetProjectByIdQuery
/// </summary>
public sealed class GetProjectByIdQueryHandler(IProjectRepository projectRepository)
    : IRequestHandler<GetProjectByIdQuery, ProjectDto?>
{
    private readonly IProjectRepository _projectRepository = projectRepository ?? throw new ArgumentNullException(nameof(projectRepository));

    public async Task<ProjectDto?> Handle(GetProjectByIdQuery request, CancellationToken cancellationToken)
    {
        // Use read-only method for query (AsNoTracking for better performance)
        var project = await _projectRepository.GetProjectByIdReadOnlyAsync(
            ProjectId.From(request.ProjectId),
            cancellationToken);

        if (project == null)
        {
            return null; // Return null instead of throwing exception - Controller will convert to 404
        }

        return MapToDto(project);
    }

    private static ProjectDto MapToDto(Project project)
    {
        return new ProjectDto
        {
            Id = project.Id.Value,
            Name = project.Name,
            Description = project.Description,
            Key = project.Key.Value,
            Status = project.Status.Name,
            OwnerId = project.OwnerId.Value,
            CreatedAt = project.CreatedAt,
            UpdatedAt = project.UpdatedAt,
            Epics = project.Epics.Select(e => new EpicDto
            {
                Id = e.Id.Value,
                Name = e.Name,
                Description = e.Description,
                ProjectId = e.ProjectId.Value,
                Status = e.Status.Name,
                Priority = e.Priority.Name,
                CreatedBy = e.CreatedBy.Value,
                CreatedAt = e.CreatedAt,
                UpdatedAt = e.UpdatedAt,
                Stories = e.Stories.Select(s => new StoryDto
                {
                    Id = s.Id.Value,
                    Title = s.Title,
                    Description = s.Description,
                    EpicId = s.EpicId.Value,
                    Status = s.Status.Name,
                    Priority = s.Priority.Name,
                    AssigneeId = s.AssigneeId?.Value,
                    EstimatedHours = s.EstimatedHours,
                    ActualHours = s.ActualHours,
                    CreatedBy = s.CreatedBy.Value,
                    CreatedAt = s.CreatedAt,
                    UpdatedAt = s.UpdatedAt,
                    Tasks = s.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()
            }).ToList()
        };
    }
}
