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.Queries.GetTasksByStoryId;

/// <summary>
/// Handler for GetTasksByStoryIdQuery
/// </summary>
public sealed class GetTasksByStoryIdQueryHandler(
    IProjectRepository projectRepository,
    ITenantContext tenantContext)
    : IRequestHandler<GetTasksByStoryIdQuery, List<TaskDto>>
{
    private readonly IProjectRepository _projectRepository = projectRepository ?? throw new ArgumentNullException(nameof(projectRepository));
    private readonly ITenantContext _tenantContext = tenantContext ?? throw new ArgumentNullException(nameof(tenantContext));

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

        // CRITICAL SECURITY: Verify Story belongs to current tenant before querying tasks
        var storyId = StoryId.From(request.StoryId);
        var story = await _projectRepository.GetStoryByIdReadOnlyAsync(storyId, cancellationToken);

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

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

        // Now fetch tasks (already filtered by EF Core, but we verified story ownership)
        var tasks = await _projectRepository.GetTasksByStoryIdAsync(storyId, cancellationToken);

        // Map tasks to DTOs
        return tasks.Select(task => new TaskDto
        {
            Id = task.Id.Value,
            Title = task.Title,
            Description = task.Description,
            StoryId = task.StoryId.Value,
            Status = task.Status.Name,
            Priority = task.Priority.Name,
            AssigneeId = task.AssigneeId?.Value,
            EstimatedHours = task.EstimatedHours,
            ActualHours = task.ActualHours,
            CreatedBy = task.CreatedBy.Value,
            CreatedAt = task.CreatedAt,
            UpdatedAt = task.UpdatedAt
        }).ToList();
    }
}
