using Lada.Framework.Data.Domains.Identity;
using Lada.Framework.DTO;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Accounts;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Users;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Accounts;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Users;
using Ladaer.BackEnd.Infrastructures.Services.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using SixLabors.ImageSharp;
using System.IdentityModel.Tokens.Jwt;
namespace Ladaer.BackEnd.Controllers.Identity
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class AccountController : ControllerBase
    {
        IConfiguration _configuration;
        private int STAFF_USER_TYPE = 10;
        private readonly UserManager<User> _userManager;
        private readonly IUserService _userService;

        public AccountController(IConfiguration configuration, UserManager<User> userManager, IUserService userService)
        {
            _configuration = configuration;
            _userManager = userManager;
            _userService = userService;
        }

        [HttpPost("Login")]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody] LoginModel model)
        {
            var result = new LoginResult();
            if (!ModelState.IsValid)
            {
                var allErrors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)).ToList();
                result.Result = Result.Failed;
                result.Message = string.Join("\n", allErrors);
                return Ok(result);
            }
            result = await _userService.Login(model);
            return Ok(result);
        }

        [HttpPost("Register")]
        [AllowAnonymous]
        public async Task<IActionResult> Register([FromBody] RegisterModel model)
        {
            var result = new RegisterResult();
            if (!ModelState.IsValid)
            {
                var allErrors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)).ToList();
                result.Result = Result.Failed;
                result.Message = string.Join("\n", allErrors);
                return Ok(result);
            }
            result = await _userService.RegisterStaff(model);
            return Ok(result);
        }


        [HttpPost("RefreshToken")]
        public async Task<IActionResult> RefreshToken([FromBody] RefreshTokenModel model)
        {
            var result = new LoginResult();

            result = await _userService.RefreshToken(model.RefreshToken, model.DeviceId);

            return Ok(result);
        }

        #region PASSWORD

        /// <summary>
        /// Đ?i m?t kh?u cho ngu?i dùng
        /// </summary>
        /// <param name="model">Thông tin d?i m?t kh?u</param>
        /// <returns>K?t qu? d?i m?t kh?u</returns>
        [HttpPut("ChangePassword")]
        public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordModel model)
        {
            var result = new UserResult();

            // Ki?m tra ModelState
            if (!ModelState.IsValid)
            {
                result.Result = Result.Failed;
                result.Message = "Thông tin d?i m?t kh?u chua h?p l?";
                var errors = ModelState.Values.Where(v => v.ValidationState == ModelValidationState.Invalid).ToList();
                foreach (var item in errors)
                {
                    var itemErrors = item.Errors;
                    foreach (var item2 in itemErrors)
                    {
                        result.ErrorList.Add(item2.ErrorMessage);
                    }
                }
                return Ok(result);
            }

            // L?y thông tin ngu?i dùng hi?n t?i
            var currentUser = User.GetCurrentUser();
            if (currentUser == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không xác d?nh du?c ngu?i dùng";
                return Ok(result);
            }

            // Gán thông tin ngu?i c?p nh?t
            model.UpdatedBy = currentUser.UserId;
            model.UpdatedByUserName = currentUser.UserName;
            model.UserId = currentUser.UserId;
            // Ki?m tra quy?n: ch? cho phép d?i m?t kh?u c?a chính ḿnh ho?c admin có th? d?i cho ngu?i khác
            if (model.UserId != currentUser.UserId && !User.IsInRole("Admin") && !User.IsInRole("Founder"))
            {
                result.Result = Result.Failed;
                result.Message = "B?n không có quy?n d?i m?t kh?u cho ngu?i dùng này";
                return Ok(result);
            }

            // G?i service d? d?i m?t kh?u
            result = await _userService.ChangePassword(model);
            return Ok(result);
        }

        #endregion


        



        #region Utilities



        private async Task<LoginResult> GetLoginResult(IdentityModel.Client.TokenResponse tokenResponse)
        {
            var result = new LoginResult();

            JwtSecurityTokenHandler jwtHandler = new JwtSecurityTokenHandler();
            var t = jwtHandler.ReadJwtToken(tokenResponse.AccessToken);
            var userType = t.Claims.FirstOrDefault(c => c.Type == "UserType");
            var exp = t.Claims.FirstOrDefault(c => c.Type == "exp");
            var email = t.Claims.FirstOrDefault(c => c.Type == "email");
            var fullName = t.Claims.FirstOrDefault(c => c.Type == "FullName");
            var roles = t.Claims.FirstOrDefault(c => c.Type == "Roles");
            var userId = t.Claims.FirstOrDefault(c => c.Type == "sub");
            var username = t.Claims.FirstOrDefault(c => c.Type == "preferred_username");
            var phoneNumber = t.Claims.FirstOrDefault(c => c.Type == "phone_number");

            //H? th?ng này ch? có STAFF vào du?c, khách hàng không vào du?c, FC cung không vào du?c
            if (userType != null && int.Parse(userType.Value) == STAFF_USER_TYPE)
            {
                result.Token = tokenResponse.AccessToken;
                result.RefreshToken = tokenResponse.RefreshToken;

                result.ExpiredTime = DateTimeOffset.Now.AddSeconds(tokenResponse.ExpiresIn);
                result.ExpiredTimestamp = exp != null ? long.Parse(exp.Value) : result.ExpiredTime.ToUnixTimeSeconds();
                result.Email = email != null ? email.Value : "";
                result.FullName = fullName != null ? fullName.Value : "";
                result.Roles = roles != null ? roles.Value : "";
                result.Id = userId != null ? int.Parse(userId.Value) : 0;
                result.UserName = username != null ? username.Value : "";
                result.PhoneNumber = phoneNumber != null ? phoneNumber.Value : "";

            }
            else
            {
                result.Result = Result.Failed;
                result.Message = "B?n không có quy?n truy c?p!";
            }




            return result;

        }
        private async Task<LoginResult> GetLoginResult(RefreshTokenResult tokenResponse)
        {
            var result = new LoginResult();



            JwtSecurityTokenHandler jwtHandler = new JwtSecurityTokenHandler();
            var t = jwtHandler.ReadJwtToken(tokenResponse.access_token);
            var userType = t.Claims.FirstOrDefault(c => c.Type == "UserType");
            var exp = t.Claims.FirstOrDefault(c => c.Type == "exp");
            var email = t.Claims.FirstOrDefault(c => c.Type == "email");
            var fullName = t.Claims.FirstOrDefault(c => c.Type == "FullName");
            var roles = t.Claims.FirstOrDefault(c => c.Type == "Roles");
            var userId = t.Claims.FirstOrDefault(c => c.Type == "sub");
            var username = t.Claims.FirstOrDefault(c => c.Type == "preferred_username");
            var phoneNumber = t.Claims.FirstOrDefault(c => c.Type == "phone_number");

            if (userType != null && int.Parse(userType.Value) == STAFF_USER_TYPE)
            {
                result.Token = tokenResponse.access_token;
                result.RefreshToken = tokenResponse.refresh_token;

                result.ExpiredTime = DateTimeOffset.Now.AddSeconds(tokenResponse.expires_in);
                result.ExpiredTimestamp = exp != null ? long.Parse(exp.Value) : result.ExpiredTime.ToUnixTimeSeconds();
                result.Email = email != null ? email.Value : "";
                result.FullName = fullName != null ? fullName.Value : "";
                result.Roles = roles != null ? roles.Value : "";
                result.Id = userId != null ? int.Parse(userId.Value) : 0;
                result.UserName = username != null ? username.Value : "";
                result.PhoneNumber = phoneNumber != null ? phoneNumber.Value : "";

            }
            else
            {
                result.Result = Result.Failed;
                result.Message = "B?n không có quy?n truy c?p!";
            }


            return result;

        }
        #endregion
    }
}
