using AsbCloudApp.Data;
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
{
    [Route("/auth")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private readonly IAuthService authService;
        private readonly IUserService userService;

        public AuthController(IAuthService authService, IUserService userService)
        {
            this.authService = authService;
            this.userService = userService;
        }

        /// <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 = default)
        {
            var userToken = await authService.LoginAsync(auth.Login,
                auth.Password, token).ConfigureAwait(false);

            if (userToken is null)
                Forbid();

            return Ok(userToken);
        }

        /// <summary>
        /// Продление срока действия токена
        /// </summary>
        /// <returns code="200">новый токен</returns>
        [Authorize]
        [HttpGet("refresh")]
        public IActionResult Refresh()
        {
            var newToken = authService.Refresh(User);
            return Ok(newToken);
        }

        /// <summary>
        /// Отправить заявку на регистрацию. Заявка подтверждается администратором.
        /// </summary>
        /// <param name="user">Информация о новом пользователе</param>
        /// <returns code="200">Ок</returns>
        [HttpPost]
        public IActionResult Register(UserRegistrationDto user)
        {
            var code = authService.Register(user);
            return code switch
            {
                0 => Ok(),
                -1 => BadRequest("Логин должен быть длиннее 3х знаков."),
                -2 => BadRequest("Пароль должен быть длиннее 3х знаков."),
                -3 => BadRequest("Email не должен быть длиннее 255 знаков."),
                -4 => BadRequest("Телефон не должен быть длиннее 50 знаков."),
                -5 => BadRequest("Название должности не должно быть длиннее 255 символов."),
                -6 => BadRequest("Пользователь с таким логином уже зарегистрирован."),
                _ => BadRequest(),
            };
        }

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

            if (editorUserId is null)
                return Forbid();

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

            var code = authService.ChangePassword(idUser, newPassword);
            return code switch
            {
                0 => Ok(),
                -1 => BadRequest("Нет такого пользователя"),
                _ => BadRequest(),
            };
        }
    }
}