using API.BusinessLogic;
using API.Models.UserModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace API.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class UserController : Controller
    {
        private readonly UserLogic _userLogic;

        public UserController(UserLogic userLogic)
        {
            _userLogic = userLogic;
        }

        /// <summary>
        /// Gets the users email and username
        /// </summary>
        /// <returns>returns the users email, username and Id</returns>
        [Authorize]
        [HttpGet("get")]
        public async Task<IActionResult> ReadUser()
        {
            var claims = HttpContext.User.Claims;
            string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
            int userId = Convert.ToInt32(userIdString);
            return await _userLogic.GetUser(userId);
        }

        /// <summary>
        /// Logins a user
        /// </summary>
        /// <param name="loginDTO">The users login credentials</param>
        /// <returns>Returns a jwttoken their username, id and a refreshtoken</returns>
        [HttpPost("login")]
        public async Task<IActionResult> Login([FromBody] LoginDTO loginDTO)
        {
            return await _userLogic.Login(loginDTO);
        }

        /// <summary>
        /// Create a new user
        /// </summary>
        /// <param name="userDTO">contains the username email and password</param>
        /// <returns>returns a okobjectresult with a boolean that is true if it fails it returns a confliftobjectresult with a message of why it failed</returns>
        [HttpPost("create")]
        public async Task<IActionResult> CreateUser([FromBody] CreateUserDTO userDTO)
        {
            return await _userLogic.RegisterUser(userDTO);
        }

        /// <summary>
        /// Changes the password of the user
        /// </summary>
        /// <param name="passwordDTO">Contains the old password and the new one</param>
        /// <returns>returns a okobjectresult with a boolean that is true if it fails it returns a confliftobjectresult with a message of why it failed</returns>
        [Authorize]
        [HttpPut("change-password")]
        public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordDTO passwordDTO)
        {
            var claims = HttpContext.User.Claims;
            string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
            int userId = Convert.ToInt32(userIdString);
            return await _userLogic.ChangePassword(passwordDTO, userId);
        }

        /// <summary>
        /// Edits the email and username of the user
        /// </summary>
        /// <param name="userDTO">The updated username and email</param>
        /// <returns>returns a okobjectresult with a boolean that is true if it fails it returns a confliftobjectresult with a message of why it failed</returns>
        [Authorize]
        [HttpPut("update")]
        public async Task<IActionResult> UpdateUser([FromBody] UpdateUserDTO userDTO)
        {
            var claims = HttpContext.User.Claims;
            string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
            int userId = Convert.ToInt32(userIdString);
            return await _userLogic.EditProfile(userDTO, userId);
        }

        /// <summary>
        /// Deletes the user
        /// </summary>
        /// <returns>returns a okobjectresult with a boolean that is true if it fails it returns a confliftobjectresult with a message of why it failed</returns>
        [Authorize]
        [HttpDelete("delete")]
        public async Task<IActionResult> DeleteUser()
        {
            var claims = HttpContext.User.Claims;
            string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
            int userId = Convert.ToInt32(userIdString);
            return await _userLogic.DeleteUser(userId);
        }

        /// <summary>
        /// For when the jwt token is outdated
        /// </summary>
        /// <param name="refreshToken">contains a string with the refreshtoken</param>
        /// <returns>returns a new refreshtoken and new jwt token</returns>
        [HttpPost("refreshtoken")]
        public async Task<IActionResult> RefreashToken([FromBody] RefreshTokenDTO refreshToken)
        {
            var token = refreshToken.RefreshToken;
            return await _userLogic.RefreshToken(token);
        }
    }
}