using MediatR;
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.DeleteStory;

/// <summary>
/// Handler for DeleteStoryCommand
/// </summary>
public sealed class DeleteStoryCommandHandler(
    IProjectRepository projectRepository,
    IUnitOfWork unitOfWork,
    ITenantContext tenantContext)
    : IRequestHandler<DeleteStoryCommand, Unit>
{
    private readonly IProjectRepository _projectRepository = projectRepository ?? throw new ArgumentNullException(nameof(projectRepository));
    private readonly IUnitOfWork _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
    private readonly ITenantContext _tenantContext = tenantContext ?? throw new ArgumentNullException(nameof(tenantContext));

    public async Task<Unit> Handle(DeleteStoryCommand request, CancellationToken cancellationToken)
    {
        // Get current tenant ID (Defense in Depth - Layer 2)
        var currentTenantId = _tenantContext.GetCurrentTenantId();

        // Get the project with story (Global Query Filter ensures tenant isolation)
        var storyId = StoryId.From(request.StoryId);
        var project = await _projectRepository.GetProjectWithStoryAsync(storyId, cancellationToken);

        if (project == null)
            throw new NotFoundException("Story", request.StoryId);

        // CRITICAL SECURITY: Explicit TenantId validation (Defense in Depth)
        if (project.TenantId.Value != currentTenantId)
            throw new NotFoundException("Story", request.StoryId);

        // Find the epic containing the story
        var epic = project.Epics.FirstOrDefault(e => e.Stories.Any(s => s.Id.Value == request.StoryId));
        if (epic == null)
            throw new NotFoundException("Story", request.StoryId);

        // Remove story from epic (domain logic validates no tasks exist)
        epic.RemoveStory(storyId);

        // Save changes
        _projectRepository.Update(project);
        await _unitOfWork.SaveChangesAsync(cancellationToken);

        return Unit.Value;
    }
}
