
using Atomx.Admin.Client.Models;
using Atomx.Admin.Client.Validators;
using Atomx.Admin.Services;
using Atomx.Admin.Utils;
using Atomx.Common.Models;
using Atomx.Common.Utils;
using Atomx.Data;
using Atomx.Data.CacheServices;
using Atomx.Data.Services;
using Atomx.Utils.Extension;
using MapsterMapper;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Atomx.Admin.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SignController : ControllerBase
    {
        readonly ILogger<SignController> _logger;
        readonly IdentityService _identityService;
        readonly IIdCreatorService _idCreator;
        readonly IMapper _mapper;
        readonly DataContext _dbContext;
        readonly JwtSetting _jwtSetting;
        readonly ICacheService _cacheService;
        readonly AuthenticationStateProvider _authenticationStateProvider;

        public SignController(ILogger<SignController> logger, IdentityService identityService, IIdCreatorService idCreator, IMapper mapper, DataContext dbContext, JwtSetting jwtSetting, ICacheService cacheService, AuthenticationStateProvider authenticationStateProvider)
        {
            _logger = logger;
            _identityService = identityService;
            _idCreator = idCreator;
            _mapper = mapper;
            _dbContext = dbContext;
            _jwtSetting = jwtSetting;
            _cacheService = cacheService;
            _authenticationStateProvider = authenticationStateProvider;
        }

        /// <summary>
        /// 用户登录系统
        /// </summary>
        /// <returns></returns>
        [HttpPost("in")]
        [AllowAnonymous]
        public async Task<IActionResult> Login(LoginModel model)
        {
            var validator = new LoginModelValidator();
            var validation = validator.Validate(model);

            if (!validation.IsValid)
            {
                var message = validation.Errors.FirstOrDefault()?.ErrorMessage;
                var result = new ApiResult<string>().IsFail(message ?? string.Empty, null);
                return new JsonResult(result);
            }

            var tokenHandler = new JwtSecurityTokenHandler();
            var issuer = _jwtSetting.Issuer;
            var audience = _jwtSetting.Audience;
            var securityKey = _jwtSetting.SecurityKey;

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            Common.Entities.Admin? user = null;
            if (model.Account.Contains("@"))
            {
                user = _dbContext.Admins.Where(p => p.Email == model.Account).SingleOrDefault();
            }
            else
            {
                user = _dbContext.Admins.Where(p => p.Username == model.Account).SingleOrDefault();
            }

            if (user == null)
            {
                var result = new ApiResult<string>().IsFail("用户不存在", null);
                return new JsonResult(result);
            }
            if (user.Password != model.Password.ToMd5Password())
            {
                var result = new ApiResult<string>().IsFail("账号密码不正确", null);
                return new JsonResult(result);
            }

            var role = _dbContext.Roles.Where(p => p.Id == user.RoleId).SingleOrDefault();

            var claims = new List<Claim>()
              {
                    new Claim(ClaimKeys.Id, user.Id.ToString()),
                    new Claim(ClaimKeys.Email, user.Email),
                    new Claim(ClaimKeys.Name, user.Username),
                    new Claim(ClaimKeys.Role, user.RoleId.ToString()),
                    new Claim(ClaimKeys.Permission, role?.Permission??string.Empty)
                };

            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);


            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = claimsIdentity,

                Expires = DateTime.UtcNow.AddMinutes(_jwtSetting.AccessTokenExpirationMinutes),
                SigningCredentials = credentials,
                Issuer = issuer,
                Audience = audience
            };

            var tokenString = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));

            var loginResult = new ApiResult<string>().IsSuccess(tokenString);

            user.LastLogin = DateTime.UtcNow;
            user.LastIp = _identityService.GetClientIp();
            user.LoginCount++;

           //((PersistingRevalidatingAuthenticationStateProvider) _authenticationStateProvider).

            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

            return new JsonResult(loginResult);

        }

        /// <summary>
        /// 用户退出系统
        /// </summary>
        /// <returns></returns>
        [HttpGet("out")]
        [AllowAnonymous]
        public async Task<IActionResult> LogoutAsync()
        {
            await HttpContext.SignOutAsync();
            return new JsonResult(new ApiResult<string>());
        }
    }
}
