using MediatR;
using ColaFlow.Modules.IssueManagement.Application.DTOs;
using ColaFlow.Modules.IssueManagement.Domain.Entities;
using ColaFlow.Modules.IssueManagement.Domain.Repositories;

namespace ColaFlow.Modules.IssueManagement.Application.Commands.CreateIssue;

public sealed class CreateIssueCommandHandler : IRequestHandler<CreateIssueCommand, IssueDto>
{
    private readonly IIssueRepository _issueRepository;
    private readonly IUnitOfWork _unitOfWork;
    private readonly IPublisher _publisher;

    public CreateIssueCommandHandler(
        IIssueRepository issueRepository,
        IUnitOfWork unitOfWork,
        IPublisher publisher)
    {
        _issueRepository = issueRepository;
        _unitOfWork = unitOfWork;
        _publisher = publisher;
    }

    public async Task<IssueDto> Handle(CreateIssueCommand request, CancellationToken cancellationToken)
    {
        // Create Issue aggregate
        var issue = Issue.Create(
            request.ProjectId,
            request.TenantId,
            request.Title,
            request.Description,
            request.Type,
            request.Priority,
            request.ReporterId
        );

        // Persist to database
        await _issueRepository.AddAsync(issue, cancellationToken);
        await _unitOfWork.SaveChangesAsync(cancellationToken);

        // Publish domain events
        foreach (var domainEvent in issue.DomainEvents)
        {
            await _publisher.Publish(domainEvent, cancellationToken);
        }
        issue.ClearDomainEvents();

        // Return DTO
        return new IssueDto
        {
            Id = issue.Id,
            ProjectId = issue.ProjectId,
            TenantId = issue.TenantId,
            Title = issue.Title,
            Description = issue.Description,
            Type = issue.Type.ToString(),
            Status = issue.Status.ToString(),
            Priority = issue.Priority.ToString(),
            AssigneeId = issue.AssigneeId,
            ReporterId = issue.ReporterId,
            CreatedAt = issue.CreatedAt,
            UpdatedAt = issue.UpdatedAt
        };
    }
}
