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

namespace ColaFlow.Modules.ProjectManagement.Application.Commands.CreateEpic;

/// <summary>
/// Handler for CreateEpicCommand
/// </summary>
public sealed class CreateEpicCommandHandler(
    IProjectRepository projectRepository,
    IUnitOfWork unitOfWork)
    : IRequestHandler<CreateEpicCommand, EpicDto>
{
    private readonly IProjectRepository _projectRepository = projectRepository ?? throw new ArgumentNullException(nameof(projectRepository));
    private readonly IUnitOfWork _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));

    public async Task<EpicDto> Handle(CreateEpicCommand request, CancellationToken cancellationToken)
    {
        // Get the project (Global Query Filter ensures tenant isolation)
        var projectId = ProjectId.From(request.ProjectId);
        var project = await _projectRepository.GetByIdAsync(projectId, cancellationToken);

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

        // Create epic through aggregate root (Project passes its TenantId)
        var createdById = UserId.From(request.CreatedBy);
        var epic = project.CreateEpic(request.Name, request.Description, createdById);

        // Update project (epic is part of aggregate)
        _projectRepository.Update(project);
        await _unitOfWork.SaveChangesAsync(cancellationToken);

        // Map to DTO
        return new EpicDto
        {
            Id = epic.Id.Value,
            Name = epic.Name,
            Description = epic.Description,
            ProjectId = epic.ProjectId.Value,
            Status = epic.Status.Name,
            Priority = epic.Priority.Name,
            CreatedBy = epic.CreatedBy.Value,
            CreatedAt = epic.CreatedAt,
            UpdatedAt = epic.UpdatedAt,
            Stories = new List<StoryDto>()
        };
    }
}
