using IWS5.Api.Helpers;
using IWS5.Core.DTO;
using IWS5.Core.Models;
using IWS5.Core.Models.Request;
using IWS5.Core.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;

namespace IWS5.Api.Controllers;

/// <summary>
/// Controller for handling authentication.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class AuthenticationController(
    IAuthenticationService authenticationService,
    ILogger<AuthenticationController> logger)
    : ControllerBase
{
    /// <summary>
    /// Authenticates a user and retrieves a bearer token for API access.
    /// </summary>
    /// <param name="logInCredentials">The user credentials including username and password.</param>
    /// <returns>Bearer token with expiration date if authentication is successful.</returns>
    /// <response code="200">Returns the bearer token and its expiration date upon successful authentication.</response>
    /// <response code="400">If the login credentials are invalid or the request is malformed.</response>
    /// <response code="401">If authentication fails due to incorrect username or password.</response>
    /// <response code="500">If there is an internal server error during authentication.</response>
    [HttpPost("login")]
    [SwaggerOperation(Summary = "Retrieves folder fields for a given work item reference ID.")]
    [ProducesResponseType(typeof(CodeResponse<LogInResponseDto>), 200)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> Login([FromBody] LogInCredentials logInCredentials)
    {
        logger.LogInformation("Login attempt for user {Username}", logInCredentials.UserName);
        var result = await authenticationService.Login(logInCredentials);
        var response = ResponseMapper<LogInResponseDto>.MapServiceResponse(result);
        return response;
    }

    /// <summary>
    /// Refreshes the authentication token.
    /// </summary>
    /// <param name="refreshTokenRequest">The request containing the refresh token.</param>
    /// <returns>New bearer token and its expiration date.</returns>
    /// <response code="200">Returns the new bearer token and its expiration date.</response>
    /// <response code="400">If the request is invalid.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpPost("refresh")]
    [Authorize]
    [SwaggerOperation(Summary = "Refreshes the authentication token.")]
    [ProducesResponseType(typeof(CodeResponse<LogInResponseDto>), 200)]
    [ProducesResponseType(400)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> RefreshToken([FromBody] RefreshTokenRequest refreshTokenRequest)
    {
        var result = await authenticationService.RefreshTokenAsync(refreshTokenRequest);
        var response = ResponseMapper<LogInResponseDto>.MapServiceResponse(result);
        return response;
    }
    
    /// <summary>
    /// Logs out the user and invalidates the refresh token.
    /// </summary>
    /// <param name="logOutRequest">The request containing the user information to log out.</param>
    /// <returns>Indicates whether the logout was successful.</returns>
    /// <response code="200">If the logout was successful.</response>
    /// <response code="400">If the request is invalid.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpPost("logout")]
    [Authorize]
    [SwaggerOperation(Summary = "Logs out the user and invalidates the refresh token.")]
    [ProducesResponseType(typeof(CodeResponse<LogOutResponseDto>), 200)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> Logout([FromBody] LogOutRequest logOutRequest)
    {
        var result = await authenticationService.LogOut(logOutRequest);
        var response = ResponseMapper<LogOutResponseDto>.MapServiceResponse(result);
        return response;
    }
}