using LSFE.Domain.Contracts;
using LSFE.Infrastructure.Entities;
using LSFE.Infrastructure.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace LSFE.API.Controllers.Account
{
    [Route("api/[controller]")]
    [ApiController]
    public class AnonAccountController : ControllerBase
    {
        public readonly UserManager<AppsUsers> _userManager;
        public readonly SignInManager<AppsUsers> _signInManager;

        public AnonAccountController(UserManager<AppsUsers> userManager,
            SignInManager<AppsUsers> signInManager)
        {
            _userManager = userManager;
            _signInManager = signInManager;
        }
        [AllowAnonymous]
        [HttpPost("GetToken")]
        public async Task<IActionResult> GetToken([FromBody] Users request,
            [FromServices] IAccountService tokenService)
        {
            var user = await _userManager.FindByNameAsync(request.UserName.ToLower());
            if (user == null)
                return Unauthorized("Invalid username or password");

            var signInResult = await _signInManager.CheckPasswordSignInAsync(user, request.Password, false);
            if (!signInResult.Succeeded)
                return Unauthorized("Invalid username or password");

            var token = await tokenService.CreateToken(user);

            return Ok(new
            {
                token,
                expiration = DateTime.UtcNow.AddMinutes(30)
            });
        }
        [AllowAnonymous]
        [HttpPost("Login")]
        public async Task<IActionResult> Login([FromBody] Users model,
            [FromServices] IAccountService tokenService)
        {
            var user = await _userManager.FindByNameAsync(model.UserName.ToLower());
            if (user == null)
                return BadRequest(new Infrastructure.Model.Response
                {
                    Success = false,
                    MessCode = 0,
                    Message = "Invalid username or password."
                });

            var signInResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);

            if (signInResult.Succeeded)
            {
                await HandleSuccessfulLogin(user);

                var token = await tokenService.CreateToken(user);
                return Ok(new
                {
                    token,
                    expiration = DateTime.Now.AddMinutes(30),
                    userId = user.Id,
                    userName = user.UserName,
                    fullName = user.FullName,
                    email = user.Email,
                    phoneNumber = user.PhoneNumber,
                    employeeId = user.EmployeeId,
                    company = user.Company,
                    Success = true,
                    MessCode = 1,
                    Message = "Yehey!"
                });
            }

            return await HandleFailedLogin(user, signInResult);
        }
        protected async Task HandleSuccessfulLogin(AppsUsers user)
        {
            if (user.LockoutEnabled || user.LockoutEnd != null)
            {
                await _userManager.SetLockoutEnabledAsync(user, false);
                user.LockoutEnd = null;
                await _userManager.UpdateAsync(user);
            }

            await _userManager.ResetAccessFailedCountAsync(user);
        }
        protected async Task<IActionResult> HandleFailedLogin(AppsUsers user,
            Microsoft.AspNetCore.Identity.SignInResult signInResult)
        {
            await _userManager.AccessFailedAsync(user);

            if (user.AccessFailedCount > 3 || signInResult.IsLockedOut)
            {
                await _userManager.SetLockoutEnabledAsync(user, true);
                await _userManager.SetLockoutEndDateAsync(user, DateTime.Now.AddMinutes(30));

                return BadRequest(new Infrastructure.Model.Response
                {
                    Success = false,
                    MessCode = 0,
                    Message = "Account is locked. Please try again after 30 minutes or contact support."
                });
            }

            return BadRequest(new Infrastructure.Model.Response
            {
                Success = false,
                MessCode = 0,
                Message = "Invalid username or password, please double check!"
            });
        }
    }
}