using MediatR;
using Microsoft.AspNetCore.Mvc;
using ColaFlow.Modules.ProjectManagement.Application.DTOs;
using ColaFlow.Modules.ProjectManagement.Application.Commands.CreateStory;
using ColaFlow.Modules.ProjectManagement.Application.Commands.UpdateStory;
using ColaFlow.Modules.ProjectManagement.Application.Commands.DeleteStory;
using ColaFlow.Modules.ProjectManagement.Application.Commands.AssignStory;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetStoryById;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetStoriesByEpicId;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetStoriesByProjectId;

namespace ColaFlow.API.Controllers;

/// <summary>
/// Stories API Controller
/// </summary>
[ApiController]
[Route("api/v1")]
public class StoriesController(IMediator mediator) : ControllerBase
{
    private readonly IMediator _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));

    /// <summary>
    /// Get story by ID
    /// </summary>
    [HttpGet("stories/{id:guid}")]
    [ProducesResponseType(typeof(StoryDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetStory(Guid id, CancellationToken cancellationToken = default)
    {
        var query = new GetStoryByIdQuery(id);
        var result = await _mediator.Send(query, cancellationToken);

        if (result == null)
        {
            return NotFound();
        }

        return Ok(result);
    }

    /// <summary>
    /// Get all stories for an epic
    /// </summary>
    [HttpGet("epics/{epicId:guid}/stories")]
    [ProducesResponseType(typeof(List<StoryDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetEpicStories(Guid epicId, CancellationToken cancellationToken = default)
    {
        var query = new GetStoriesByEpicIdQuery(epicId);
        var result = await _mediator.Send(query, cancellationToken);
        return Ok(result);
    }

    /// <summary>
    /// Get all stories for a project
    /// </summary>
    [HttpGet("projects/{projectId:guid}/stories")]
    [ProducesResponseType(typeof(List<StoryDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetProjectStories(Guid projectId, CancellationToken cancellationToken = default)
    {
        var query = new GetStoriesByProjectIdQuery(projectId);
        var result = await _mediator.Send(query, cancellationToken);
        return Ok(result);
    }

    /// <summary>
    /// Create a new story (independent endpoint)
    /// </summary>
    [HttpPost("stories")]
    [ProducesResponseType(typeof(StoryDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> CreateStoryIndependent(
        [FromBody] CreateStoryCommand command,
        CancellationToken cancellationToken = default)
    {
        var result = await _mediator.Send(command, cancellationToken);
        return CreatedAtAction(nameof(GetStory), new { id = result.Id }, result);
    }

    /// <summary>
    /// Create a new story (nested endpoint)
    /// </summary>
    [HttpPost("epics/{epicId:guid}/stories")]
    [ProducesResponseType(typeof(StoryDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> CreateStory(
        Guid epicId,
        [FromBody] CreateStoryRequest request,
        CancellationToken cancellationToken = default)
    {
        var command = new CreateStoryCommand
        {
            EpicId = epicId,
            Title = request.Title,
            Description = request.Description,
            Priority = request.Priority,
            AssigneeId = request.AssigneeId,
            EstimatedHours = request.EstimatedHours,
            CreatedBy = request.CreatedBy
        };

        var result = await _mediator.Send(command, cancellationToken);
        return CreatedAtAction(nameof(GetStory), new { id = result.Id }, result);
    }

    /// <summary>
    /// Update an existing story
    /// </summary>
    [HttpPut("stories/{id:guid}")]
    [ProducesResponseType(typeof(StoryDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> UpdateStory(
        Guid id,
        [FromBody] UpdateStoryRequest request,
        CancellationToken cancellationToken = default)
    {
        var command = new UpdateStoryCommand
        {
            StoryId = id,
            Title = request.Title,
            Description = request.Description,
            Status = request.Status,
            Priority = request.Priority,
            AssigneeId = request.AssigneeId,
            EstimatedHours = request.EstimatedHours
        };

        var result = await _mediator.Send(command, cancellationToken);

        if (result == null)
        {
            return NotFound();
        }

        return Ok(result);
    }

    /// <summary>
    /// Delete a story
    /// </summary>
    [HttpDelete("stories/{id:guid}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> DeleteStory(Guid id, CancellationToken cancellationToken = default)
    {
        var command = new DeleteStoryCommand { StoryId = id };
        await _mediator.Send(command, cancellationToken);
        return NoContent();
    }

    /// <summary>
    /// Assign a story to a user
    /// </summary>
    [HttpPut("stories/{id:guid}/assign")]
    [ProducesResponseType(typeof(StoryDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> AssignStory(
        Guid id,
        [FromBody] AssignStoryRequest request,
        CancellationToken cancellationToken = default)
    {
        var command = new AssignStoryCommand
        {
            StoryId = id,
            AssigneeId = request.AssigneeId
        };

        var result = await _mediator.Send(command, cancellationToken);

        if (result == null)
        {
            return NotFound();
        }

        return Ok(result);
    }
}

/// <summary>
/// Request model for creating a story
/// </summary>
public record CreateStoryRequest
{
    public string Title { get; init; } = string.Empty;
    public string Description { get; init; } = string.Empty;
    public string Priority { get; init; } = "Medium";
    public Guid? AssigneeId { get; init; }
    public decimal? EstimatedHours { get; init; }
    public Guid CreatedBy { get; init; }
}

/// <summary>
/// Request model for updating a story
/// </summary>
public record UpdateStoryRequest
{
    public string Title { get; init; } = string.Empty;
    public string Description { get; init; } = string.Empty;
    public string? Status { get; init; }
    public string? Priority { get; init; }
    public Guid? AssigneeId { get; init; }
    public decimal? EstimatedHours { get; init; }
}

/// <summary>
/// Request model for assigning a story
/// </summary>
public record AssignStoryRequest
{
    public Guid AssigneeId { get; init; }
}
