using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Tiobon.Core.AuthHelper;
using Tiobon.Core.AuthHelper.OverWrite;
using Tiobon.Core.Common.Swagger;


namespace Tiobon.Core.Controllers;

/// <summary>
/// 登录管理【无权限】
/// </summary>
[Produces("application/json")]
[Route("api/[controller]")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_Auth)]
[AllowAnonymous]
public class AuthorizeController : BaseApiController
{
    readonly ISysUserInfoServices _sysUserInfoServices;
    readonly IGhrs_UserServices _ghrs_UserServices;
    readonly PermissionRequirement _requirement;
    private readonly IRoleModulePermissionServices _roleModulePermissionServices;
    private readonly ILogger<AuthorizeController> _logger;

    /// <summary>
    /// 构造函数注入
    /// </summary>
    /// <param name="sysUserInfoServices"></param> 
    /// <param name="ghrs_UserServices"></param> 
    /// <param name="requirement"></param>
    /// <param name="roleModulePermissionServices"></param>
    /// <param name="logger"></param>
    public AuthorizeController(ISysUserInfoServices sysUserInfoServices, IGhrs_UserServices ghrs_UserServices, PermissionRequirement requirement, IRoleModulePermissionServices roleModulePermissionServices, ILogger<AuthorizeController> logger)
    {
        this._sysUserInfoServices = sysUserInfoServices;
        this._ghrs_UserServices = ghrs_UserServices;
        _requirement = requirement;
        _roleModulePermissionServices = roleModulePermissionServices;
        _logger = logger;
    }


    #region 获取token的第1种方法

    /// <summary>
    /// 获取JWT的方法1
    /// </summary>
    /// <param name="name"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    [NonAction]
    [HttpGet, Route("Token")]
    public async Task<ServiceResult<string>> GetJwtStr(string name, string pass)
    {
        string jwtStr = string.Empty;
        bool suc = false;
        //这里就是用户登陆以后，通过数据库去调取数据，分配权限的操作

        var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass));
        if (user != null)
        {
            TokenModelJwt tokenModel = new TokenModelJwt { Uid = 1, Role = user };

            jwtStr = JwtHelper.IssueJwt(tokenModel);
            suc = true;
        }
        else
            jwtStr = "login fail!!!";

        return new ServiceResult<string>()
        {
            Success = suc,
            Message = suc ? "获取成功" : "获取失败",
            Data = jwtStr
        };
    }


    /// <summary>
    /// 获取JWT的方法2：给Nuxt提供
    /// </summary>
    /// <param name="name"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    [HttpGet]
    [NonAction]
    [Route("GetTokenNuxt")]
    public ServiceResult<string> GetJwtStrForNuxt(string name, string pass)
    {
        string jwtStr = string.Empty;
        bool suc = false;
        //这里就是用户登陆以后，通过数据库去调取数据，分配权限的操作
        //这里直接写死了
        if (name == "admins" && pass == "admins")
        {
            TokenModelJwt tokenModel = new TokenModelJwt
            {
                Uid = 1,
                Role = "Admin"
            };

            jwtStr = JwtHelper.IssueJwt(tokenModel);
            suc = true;
        }
        else
            jwtStr = "login fail!!!";

        //var result = new
        //{
        //    data = new { success = suc, token = jwtStr }
        //};

        return new ServiceResult<string>()
        {
            Success = suc,
            Message = suc ? "获取成功" : "获取失败",
            Data = jwtStr
        };
    }

    #endregion


    /// <summary>
    /// 获取JWT的方法3：整个系统主要方法
    /// </summary>
    /// <param name="name"></param>
    /// <param name="pass"></param>
    /// <returns></returns>
    [NonAction]
    [HttpGet, Route("JWTToken3.0")]
    public async Task<ServiceResult<TokenInfoViewModel>> GetJwtToken3(string name = "", string pass = "")
    {
        string jwtStr = string.Empty;

        if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
            return Failed<TokenInfoViewModel>("用户名或密码不能为空");

        pass = MD5Helper.MD5Encrypt32(pass);

        var user = await _sysUserInfoServices.Query(d =>
            d.LoginName == name && d.LoginPWD == pass && d.IsDeleted == false);
        if (user.Count > 0)
        {
            var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(name, pass);
            //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name,  user.FirstOrDefault().Id.ToString()),
                new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()),
                new Claim("TenantId", user.FirstOrDefault().TenantId.ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.DateToTimeStamp()),
                new Claim(ClaimTypes.Expiration,
                    DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
            };
            claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));


            // ids4和jwt切换
            // jwt
            if (!Permissions.IsUseIds4)
            {
                var data = await _roleModulePermissionServices.RoleModuleMaps();
                var list = (from item in data
                            where item.IsDeleted == false
                            orderby item.Id
                            select new PermissionItem
                            {
                                Url = item.Module?.LinkUrl,
                                Role = item.Role?.Name.ObjToString(),
                            }).ToList();

                _requirement.Permissions = list;
            }

            var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
            return Success(token, "获取成功");
        }
        else
            return Failed<TokenInfoViewModel>("认证失败");
    }

    [NonAction]
    [HttpGet, Route("GetJwtTokenSecret")]
    public async Task<ServiceResult<TokenInfoViewModel>> GetJwtTokenSecret(string name = "", string pass = "")
    {
        var rlt = await GetJwtToken3(name, pass);
        return rlt;
    }

    /// <summary>
    /// 请求刷新Token（以旧换新）
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    [HttpGet, Route("RefreshToken")]
    public async Task<ServiceResult<TokenInfoViewModel>> RefreshToken(string token = "")
    {
        string jwtStr = string.Empty;

        if (string.IsNullOrEmpty(token))
            return Failed<TokenInfoViewModel>("token无效，请重新登录！");
        var tokenModel = JwtHelper.SerializeJwt(token);
        if (tokenModel != null && JwtHelper.customSafeVerify(token) && tokenModel.Uid > 0)
        {
            var user = await _sysUserInfoServices.QueryById(tokenModel.Uid);
            var value = User.Claims.SingleOrDefault(s => s.Type == JwtRegisteredClaimNames.Iat)?.Value;
            if (value != null && user.CriticalModifyTime > value.ObjToDate())
                return Failed<TokenInfoViewModel>("很抱歉,授权已失效,请重新授权！");

            if (user != null && !(value != null && user.CriticalModifyTime > value.ObjToDate()))
            {
                var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(user.LoginName, user.LoginPWD);
                //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, user.LoginName),
                    new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.DateToTimeStamp()),
                    new Claim(ClaimTypes.Expiration,
                        DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
                };
                claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));

                //用户标识
                var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
                identity.AddClaims(claims);

                var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
                return Success(refreshToken, "获取成功");
            }
        }

        return Failed<TokenInfoViewModel>("认证失败！");
    }

    #region 用户登录
    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="loginRequest"></param>
    /// <returns></returns>
    [HttpPost, Route("Login")]
    public async Task<dynamic> Login([FromBody] SwaggerLoginRequest loginRequest)
    {
        if (loginRequest is null)
            return new { result = false };

        try
        {
            var result = await GetJwtToken3(loginRequest.name, loginRequest.pwd);
            if (result.Success)
            {
                HttpContext.SuccessSwagger();
                HttpContext.SuccessSwaggerJwt(result.Data.token);
                return new { result = true };
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Swagger登录异常");
        }

        return new { result = false };
    }

    /// <summary>
    /// 用户自动登录
    /// </summary>
    /// <param name="Id"></param>
    /// <returns></returns>
    [HttpGet("AutoLogin/{Id}")]
    public async Task<ServiceResult<string>> AutoLogin(long? Id)
    {
        if (Id is null)
            return Failed<string>("无效的用户ID");

        try
        {

            var user = await _ghrs_UserServices.QuerySingleDto(d => d.UserId == Id);
            if (user != null)
            {
                //如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
                var claims = new List<Claim> {
                new Claim(ClaimTypes.Name,  user.UserName.ToString()),
                new Claim(JwtRegisteredClaimNames.Jti, user.UserId.ToString()),
                new Claim("TenantId", "0"),
                new Claim("StaffId",user.UserStaffID !=null? user.UserStaffID.ToString():"0"),
                new Claim("StaffName",user.StaffName !=null?user.StaffName:"0"),
                new Claim("StaffNo", user.StaffNo !=null?user.StaffNo:"0"),
                new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.DateToTimeStamp()),
                new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
                };
                var result = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);

                if (result.success)
                {
                    HttpContext.SuccessSwagger();
                    HttpContext.SuccessSwaggerJwt(result.token);
                    return Success<string>(result.token);
                }
            }

            //            var sql = @"SELECT A.UserId,
            //       A.UserName,
            //       b.StaffNo,
            //       b.StaffName,
            //       A.UserStaffID
            //FROM Ghrs_User A LEFT JOIN Ghra_Staff b ON A.UserStaffID = b.StaffID
            //WHERE A.UserId = 1";
        }
        catch (Exception E)
        {
            _logger.LogWarning(E, E.Message);
            return Failed<string>(E.Message);
        }
        return Failed<string>("自动登录失败");
    }

    #endregion
}