using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ColaFlow.Modules.ProjectManagement.Application.Commands.CreateSprint;
using ColaFlow.Modules.ProjectManagement.Application.Commands.UpdateSprint;
using ColaFlow.Modules.ProjectManagement.Application.Commands.DeleteSprint;
using ColaFlow.Modules.ProjectManagement.Application.Commands.StartSprint;
using ColaFlow.Modules.ProjectManagement.Application.Commands.CompleteSprint;
using ColaFlow.Modules.ProjectManagement.Application.Commands.AddTaskToSprint;
using ColaFlow.Modules.ProjectManagement.Application.Commands.RemoveTaskFromSprint;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetSprintById;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetSprintsByProjectId;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetActiveSprints;
using ColaFlow.Modules.ProjectManagement.Application.Queries.GetSprintBurndown;
using ColaFlow.Modules.ProjectManagement.Application.DTOs;

namespace ColaFlow.API.Controllers;

/// <summary>
/// Sprint management endpoints
/// </summary>
[ApiController]
[Route("api/v1/sprints")]
[Authorize]
public class SprintsController : ControllerBase
{
    private readonly IMediator _mediator;

    public SprintsController(IMediator mediator)
    {
        _mediator = mediator;
    }

    /// <summary>
    /// Create a new sprint
    /// </summary>
    [HttpPost]
    public async Task<ActionResult<SprintDto>> Create([FromBody] CreateSprintCommand command)
    {
        var result = await _mediator.Send(command);
        return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
    }

    /// <summary>
    /// Update an existing sprint
    /// </summary>
    [HttpPut("{id}")]
    public async Task<IActionResult> Update(Guid id, [FromBody] UpdateSprintCommand command)
    {
        if (id != command.SprintId)
            return BadRequest("Sprint ID mismatch");

        await _mediator.Send(command);
        return NoContent();
    }

    /// <summary>
    /// Delete a sprint
    /// </summary>
    [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(Guid id)
    {
        await _mediator.Send(new DeleteSprintCommand(id));
        return NoContent();
    }

    /// <summary>
    /// Get sprint by ID
    /// </summary>
    [HttpGet("{id}")]
    public async Task<ActionResult<SprintDto>> GetById(Guid id)
    {
        var result = await _mediator.Send(new GetSprintByIdQuery(id));
        if (result == null)
            return NotFound();
        return Ok(result);
    }

    /// <summary>
    /// Get all sprints for a project
    /// </summary>
    [HttpGet]
    public async Task<ActionResult<IReadOnlyList<SprintDto>>> GetByProject([FromQuery] Guid projectId)
    {
        var result = await _mediator.Send(new GetSprintsByProjectIdQuery(projectId));
        return Ok(result);
    }

    /// <summary>
    /// Get all active sprints
    /// </summary>
    [HttpGet("active")]
    public async Task<ActionResult<IReadOnlyList<SprintDto>>> GetActive()
    {
        var result = await _mediator.Send(new GetActiveSprintsQuery());
        return Ok(result);
    }

    /// <summary>
    /// Start a sprint (Planned to Active)
    /// </summary>
    [HttpPost("{id}/start")]
    public async Task<IActionResult> Start(Guid id)
    {
        await _mediator.Send(new StartSprintCommand(id));
        return NoContent();
    }

    /// <summary>
    /// Complete a sprint (Active to Completed)
    /// </summary>
    [HttpPost("{id}/complete")]
    public async Task<IActionResult> Complete(Guid id)
    {
        await _mediator.Send(new CompleteSprintCommand(id));
        return NoContent();
    }

    /// <summary>
    /// Add a task to a sprint
    /// </summary>
    [HttpPost("{id}/tasks/{taskId}")]
    public async Task<IActionResult> AddTask(Guid id, Guid taskId)
    {
        await _mediator.Send(new AddTaskToSprintCommand(id, taskId));
        return NoContent();
    }

    /// <summary>
    /// Remove a task from a sprint
    /// </summary>
    [HttpDelete("{id}/tasks/{taskId}")]
    public async Task<IActionResult> RemoveTask(Guid id, Guid taskId)
    {
        await _mediator.Send(new RemoveTaskFromSprintCommand(id, taskId));
        return NoContent();
    }

    /// <summary>
    /// Get burndown chart data for a sprint
    /// </summary>
    [HttpGet("{id}/burndown")]
    public async Task<ActionResult<BurndownChartDto>> GetBurndown(Guid id)
    {
        var result = await _mediator.Send(new GetSprintBurndownQuery(id));
        if (result == null)
            return NotFound();
        return Ok(result);
    }
}
