using AsbCloudApp.Data;
using AsbCloudApp.Data.User;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudWebApi.Controllers;

/// <summary>
/// Авторизация
/// </summary>
[Route("/auth")]
[ApiController]
public class AuthController : ControllerBase
{
    private readonly IAuthService authService;
    private readonly IUserRepository userRepository;

    public AuthController(IAuthService authService, IUserRepository userRepository)
    {
        this.authService = authService;
        this.userRepository = userRepository;
    }

    /// <summary>
    /// Аутентификация пользователя
    /// </summary>
    /// <param name="auth"></param>
    /// <param name="token">Токен отмены задачи</param>
    /// <response code="200">новый токен</response>
    /// <response code="400">логин и пароль не подходят</response>
    [AllowAnonymous]
    [HttpPost("login")]
    [SwaggerOperation(OperationId = "login")]
    [ProducesResponseType(typeof(UserTokenDto), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> LoginAsync([FromBody] AuthDto auth, CancellationToken token)
    {
        var userToken = await authService.LoginAsync(auth.Login, auth.Password, token);

        if (userToken is null)
            Forbid();

        return Ok(userToken);
    }

    /// <summary>
    /// Продление срока действия токена
    /// </summary>
    /// <returns code="200">новый токен</returns>
    [Authorize]
    [HttpGet("refresh")]
    [ProducesResponseType(typeof(UserTokenDto), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> RefreshAsync(CancellationToken token)
    {
        var userToken = await authService.RefreshAsync(User, token);

        if (userToken is null)
            Forbid();

        return Ok(userToken);
    }

    /// <summary>
    /// Отправить заявку на регистрацию. Заявка подтверждается администратором.
    /// </summary>
    /// <param name="user">Информация о новом пользователе</param>
    /// <returns code="200">Ок</returns>
    [HttpPost]
    [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
    public IActionResult Register(UserRegistrationDto user)
    {
        authService.Register(user);
        return Ok();
    }

    /// <summary>
    /// Смена пароля пользователя. Доступна пользователю и администратору
    /// </summary>
    /// <returns code="200">Ок</returns>
    [Authorize]
    [HttpPut("{idUser}/ChangePassword")]
    [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
    public IActionResult ChangePassword([FromRoute] int idUser, [FromBody] string newPassword)
    {
        var editorUserId = User.GetUserId();

        if (editorUserId is null)
            return Forbid();

        if (!((editorUserId == idUser) || userRepository.HasPermission((int)editorUserId, "Auth.edit")))
            return Forbid();

        authService.ChangePassword(idUser, newPassword);
        return Ok();
    }
}