using Lada.Framework.Data.Domains.Categories;
using Lada.Framework.Data.Domains.Identity;
using Lada.Framework.Data.Enums;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Identity;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Users;
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 Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Controllers.Identity
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class UserController : ControllerBase
    {
        //private readonly UserManager<User> _userManager;
        private readonly IUserService _userService;

        public UserController(IUserService userService)
        {
            //_userManager = userManager;
            _userService = userService;
        }

        #region Suggestions
        [HttpGet("SugStaff")]
        [Authorize(Roles = "User.SugStaff")]
        public async Task<List<UserOptionItem>> SugStaff(string keyword = "")
        {
            return await _userService.SugUser(keyword, UserType.Staff);
        }

        [HttpGet("SugDriver")]
        [Authorize(Roles = "User.SugDriver")]
        public async Task<List<UserOptionItem>> SugDriver(string keyword = "")
        {

            return await _userService.SugUser(keyword, UserType.Staff, "Driver");
        }

        [HttpGet("SugFranchiser")]
        public async Task<List<UserOptionItem>> SugFranchiser(string keyword = "")
        {
            return await _userService.SugUser(keyword, UserType.Franchisee);
        }

        [HttpGet("SugCustomer")]
        public async Task<List<UserOptionItem>> SugCustomer(string keyword = "")
        {
            return await _userService.SugUser(keyword, UserType.Customer);
        }

        [HttpGet("AutoComplete")]
        public async Task<List<UserOptionItem>> AutoComplete(int type, string keyword = "")
        {
            return await _userService.AutoComplete(keyword, (UserType)type);
        }

        [HttpGet("AutoCompleteByAgency")]
        public async Task<List<UserOptionItem>> AutoCompleteByAgency(int agencyId, string keyword = "")
        {
            return await _userService.AutoCompleteByAgency(keyword, agencyId);
        } 
        #endregion


        #region SEARCH
        [HttpPost("SearchStaff")]
        [Authorize(Roles = "User.SearchStaff")]
        public async Task<IActionResult> SearchStaff([FromBody] SmartTableParam param)
        {
            var staffs = await _userService.Search(param, UserType.Staff);
            return Ok(staffs);
        }

        [HttpPost("SearchCustomer")]
        [Authorize(Roles = "User.SearchCustomer")]
        public async Task<IActionResult> SearchCustomer([FromBody] SmartTableParam param)
        {
            var customers = await _userService.Search(param, UserType.Customer);
            return Ok(customers);
        }
        #endregion


        #region CRUD
        [HttpGet("GetStaffById")]
        [Authorize(Roles = "User.GetStaffById")]
        public async Task<IActionResult> GetStaffById(int id)
        {
            var result = await _userService.GetStaffModelByIdAsync(id);
            return Ok(result);
        }

        [HttpPut("UpdateStaff")]
        [Authorize(Roles = "User.UpdateStaff")]
        public async Task<IActionResult> UpdateStaff([FromBody] StaffModel model)
        {
            var result = new UserResult();
            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);
            }


            model.UpdatedBy = currentUser.UserId;
            model.UpdatedByUserName = currentUser.UserName;
            if (model.UpdatedBy <= 0 || string.IsNullOrEmpty(model.UpdatedByUserName))
            {
                result.Result = Result.Failed;
                result.Message = "Không xác d?nh du?c ngu?i dùng";
                return Ok(result);
            }
            if (model.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "ID ngu?i dùng c?n c?p nh?t không h?p l?";
                return Ok(result);
            }
            result = await _userService.UpdateStaff(model);
            return Ok(result);
        }

        [HttpDelete]
        public async Task<IActionResult> DeleteStaff(int id)
        {
            var result = new UserResult();
            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);
            }


            var updatedBy = currentUser.UserId;
            var updatedByUserName = currentUser.UserName;


            if (id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "ID ngu?i dùng c?n c?p nh?t không h?p l?";
                return Ok(result);
            }

            result = await _userService.DeleteStaff(id, updatedBy, updatedByUserName);
            return Ok(result);
        }

        #endregion

        #region LOCK-UNLOCK

        [HttpPut("Lock")]
        [Authorize(Roles = "User.Lock")]
        public async Task<IActionResult> Lock([FromBody] UserStatusModel model)
        {
            var result = new UserResult();
            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);
            }


            model.UpdatedBy = currentUser.UserId;
            model.UpdatedByUserName = currentUser.UserName;


            result = await _userService.Lock(model);
            return Ok(result);

        }


        [HttpPut("UnLock")]
        [Authorize(Roles = "User.UnLock")]
        public async Task<IActionResult> UnLock([FromBody] UserStatusModel model)
        {
            var result = new UserResult();
            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);
            }


            model.UpdatedBy = currentUser.UserId;
            model.UpdatedByUserName = currentUser.UserName;


            result = await _userService.UnLock(model);
            return Ok(result);

        }

        #endregion

        #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")]
        [Authorize(Roles = "User.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;

            // 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);
        }


        [HttpPut("SetPassword")]
        [Authorize(Roles = "User.SetPassword")]
        public async Task<IActionResult> SetPassword([FromBody] SetPasswordModel 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;

            // 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.Id != currentUser.UserId && !User.IsInRole("Admin") && !User.IsInRole("Founder") && !User.IsInRole("Co-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.SetPassword(model);
            return Ok(result);
        }


        #endregion


        [HttpPost("RegisterStaff")]
        [Authorize(Roles = "User.RegisterStaff")]
        public async Task<IActionResult> RegisterStaff([FromBody] RegisterModel model)
        {
            RegisterResult result = new RegisterResult();
            if (!ModelState.IsValid)
            {
                result.Result = Result.Failed;
                result.Message = "Thông tin dang kư 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);
            }

            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);
            }
            result = await _userService.RegisterStaff(model);
            return Ok(result);
        }
    }
}
