using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MembershipService.API.Application.Commands;
using MembershipService.API.Application.Queries;
using Swashbuckle.AspNetCore.Annotations;

namespace MembershipService.API.Controllers;

/// <summary>
/// EN: Controller for managing level definitions.
/// VI: Controller để quản lý level definitions.
/// </summary>
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[Authorize]
[SwaggerTag("Level definitions management endpoints")]
public class LevelsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<LevelsController> _logger;

    public LevelsController(IMediator mediator, ILogger<LevelsController> logger)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Get all level definitions.
    /// VI: Lấy tất cả level definitions.
    /// </summary>
    [HttpGet]
    [AllowAnonymous]
    [SwaggerOperation(Summary = "Get level definitions", Description = "Retrieves all level definitions")]
    [SwaggerResponse(200, "Level definitions retrieved", typeof(IEnumerable<LevelDefinitionDto>))]
    public async Task<ActionResult<IEnumerable<LevelDefinitionDto>>> GetAll(
        [FromQuery] bool includeInactive = false)
    {
        var query = new GetLevelDefinitionsQuery { IncludeInactive = includeInactive };
        var levels = await _mediator.Send(query);
        return Ok(levels);
    }

    /// <summary>
    /// EN: Create a new level definition (Admin only).
    /// VI: Tạo level definition mới (chỉ Admin).
    /// </summary>
    [HttpPost]
    [Authorize(Roles = "Admin")]
    [SwaggerOperation(Summary = "Create level definition", Description = "Creates a new level definition (Admin only)")]
    [SwaggerResponse(201, "Level definition created", typeof(CreateLevelDefinitionResult))]
    [SwaggerResponse(400, "Invalid request")]
    [SwaggerResponse(401, "Unauthorized")]
    [SwaggerResponse(403, "Forbidden - Admin role required")]
    [SwaggerResponse(409, "Level number already exists")]
    public async Task<ActionResult<CreateLevelDefinitionResult>> Create(
        [FromBody] CreateLevelDefinitionCommand command)
    {
        try
        {
            var result = await _mediator.Send(command);
            return CreatedAtAction(nameof(GetAll), new { }, result);
        }
        catch (InvalidOperationException ex) when (ex.Message.Contains("already exists"))
        {
            return Conflict(new { message = ex.Message });
        }
        catch (ArgumentException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating level definition");
            return StatusCode(500, new { message = "An error occurred while creating level definition" });
        }
    }

    /// <summary>
    /// EN: Update an existing level definition (Admin only).
    /// VI: Cập nhật level definition (chỉ Admin).
    /// </summary>
    [HttpPut("{id:guid}")]
    [Authorize(Roles = "Admin")]
    [SwaggerOperation(Summary = "Update level definition", Description = "Updates an existing level definition (Admin only)")]
    [SwaggerResponse(200, "Level definition updated", typeof(UpdateLevelDefinitionResult))]
    [SwaggerResponse(400, "Invalid request")]
    [SwaggerResponse(401, "Unauthorized")]
    [SwaggerResponse(403, "Forbidden - Admin role required")]
    [SwaggerResponse(404, "Level definition not found")]
    public async Task<ActionResult<UpdateLevelDefinitionResult>> Update(
        Guid id,
        [FromBody] UpdateLevelDefinitionCommand command)
    {
        command.Id = id;

        try
        {
            var result = await _mediator.Send(command);
            return Ok(result);
        }
        catch (KeyNotFoundException ex)
        {
            return NotFound(new { message = ex.Message });
        }
        catch (ArgumentException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error updating level definition {LevelId}", id);
            return StatusCode(500, new { message = "An error occurred while updating level definition" });
        }
    }

    /// <summary>
    /// EN: Deactivate a level definition (Admin only, soft delete).
    /// VI: Vô hiệu hóa level definition (chỉ Admin, xóa mềm).
    /// </summary>
    [HttpDelete("{id:guid}")]
    [Authorize(Roles = "Admin")]
    [SwaggerOperation(Summary = "Deactivate level definition", Description = "Deactivates a level definition - soft delete (Admin only)")]
    [SwaggerResponse(204, "Level definition deactivated")]
    [SwaggerResponse(401, "Unauthorized")]
    [SwaggerResponse(403, "Forbidden - Admin role required")]
    [SwaggerResponse(404, "Level definition not found")]
    public async Task<IActionResult> Deactivate(Guid id)
    {
        try
        {
            await _mediator.Send(new DeactivateLevelDefinitionCommand(id));
            return NoContent();
        }
        catch (KeyNotFoundException ex)
        {
            return NotFound(new { message = ex.Message });
        }
        catch (ArgumentException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error deactivating level definition {LevelId}", id);
            return StatusCode(500, new { message = "An error occurred while deactivating level definition" });
        }
    }
}

