package com.mosty.common.core.login;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.mosty.common.base.exception.BusinessException;
import com.mosty.common.base.util.DateUtils;
import com.mosty.common.core.business.entity.SysDept;
import com.mosty.common.core.business.entity.SysUser;
import com.mosty.common.core.business.entity.vo.SysRoleVO;
import com.mosty.common.core.login.dto.DeptAllVo;
import com.mosty.common.core.login.dto.DeptDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.mosty.common.base.constant.SystemConfigConstants.TOKEN_ISSUER;
import static com.mosty.common.base.constant.SystemConfigConstants.TOKEN_KEY;

/**
 * jwt token工具类
 *
 * @author kevin
 * @date 2022/2/15 10:32 PM
 * @since 1.0.0
 */
@Slf4j
@Component
public class JwtTokenGenerator {

    /**
     * 配置文件中过期时间，单位秒
     */
    @Value("${jwt.expiration:864000}")
    private Long expiration;

    /**
     * 配置文件中的jwt秘钥
     */
    @Value("${jwt.secret:RVvjAORWxgmDyvGP8RkD7HuaYEuekN7rXyaDaLn2jbk6OJvFupTXzicR883pFUmI}")
    private String secret;

    @Value("${jwt.issuer:mosty-admin}")
    private String issuer;

    /**
     * 获取当前登陆的token
     * <p>
     * private String id;//人员主键	userId
     * private String identitycard;//人员账号
     * private String identitycard;//身份证号码
     * private String identitycard;//行业号码
     * private String username;//人员姓名
     * private String orgname;//所在部门名称
     * private String orgcode;//所在部门代码
     * private String orgid;//所在部门ID
     * private String org_level;//所在部门等级代码	[部门等级]
     * private String orgid;//所在部门业务类型代码	org_biz_type
     * private String position;//登陆时间
     *
     * @param sysUser          用户信息
     * @param dept    当前登陆用户部门
     * @return token信息
     */
    public String generateToken(SysUser sysUser, DeptAllVo dept) {
        try {
            long currentMills = System.currentTimeMillis();
            Algorithm algorithm = Algorithm.HMAC256(secret);

            Date expireDate = DateUtils.parseDate("2099-12-31 00:00:00");
            return JWT.create()
                    .withIssuer(issuer)
                    .withIssuedAt(new Date(currentMills))
                    .withClaim("userId", sysUser.getId())
                    .withClaim("userName", sysUser.getUserName())
                    .withClaim("userType", sysUser.getUserType())
                    .withClaim("userLoginName", sysUser.getLoginName())
                    .withClaim("inDustRialId", sysUser.getInDustRialId())
                    .withClaim("idEntityCard", sysUser.getIdEntityCard())
                    .withClaim("phone", sysUser.getMobile())
                    .withClaim("isVirtualUser", sysUser.getIsVirtualUser())
                    .withClaim("deptId", dept.getDeptid())
                    .withClaim("deptCode", dept.getDeptcode())
                    .withClaim("deptName", dept.getDeptname())
                    .withClaim("deptLevel", dept.getOrgLevel())
                    .withClaim("deptBizType", dept.getOrgType())
                    .withClaim("fxjDeptId", dept.getFxjid())
                    .withClaim("fxjDeptName", dept.getFxjname())
                    .withClaim("fxjDeptCode", dept.getFxjcode())
                    .withClaim("dszDeptId", dept.getDszid())
                    .withClaim("dszDeptName", dept.getDszname())
                    .withClaim("dszDeptCode", dept.getDszcode())
                    .withIssuedAt(new Date())
                    .withSubject("admin")
                    //设置时间长一点，永不过期
//                    .withExpiresAt(new Date(currentMills + expiration * 1000))
                    .withExpiresAt(expireDate)
                    .sign(algorithm);
        } catch (Exception e) {
            log.error("生产token异常", e);
            return null;
        }
    }

    public String generatePromotionToken(Long promotionId, String promotionMobile, Integer promotionType, String pageUrl) {
        try {
//            Long expiration = 7200L;
            long currentMills = System.currentTimeMillis();
            Algorithm algorithm = Algorithm.HMAC256(secret);
            /*DecodedJWT verify = verify(token, secret, issuer);
            Claim promotionMobile1 = verify.getClaims().get("promotionId");*/
            return JWT.create()
                    .withIssuer(issuer)
                    .withIssuedAt(new Date(currentMills))
                    .withClaim("promotionId", promotionId)
                    .withClaim("promotionMobile", promotionMobile)
                    .withClaim("promotionType", promotionType)
                    .withClaim("pageUrl", pageUrl)
                    .withSubject("promotion")
                    //设置过期时间为2小时
                    .withExpiresAt(new Date(currentMills + expiration * 1000))
                    .sign(algorithm);

        } catch (Exception e) {
            log.error("生产token异常:{}", e);
            return null;
        }
    }

    public Map<String, Claim> getPromotionFromToken(String token) {
        try {
            DecodedJWT decodedJWT = verify(token, secret, issuer);
            return decodedJWT.getClaims();
        } catch (Exception e) {
            throw new BusinessException("获取用户身份异常，请退出重新登录");
        }
    }

    public static DecodedJWT verify(String token, String secret, String issuer) {
        DecodedJWT result = null;
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(issuer)
                    .build();
            DecodedJWT decodedJWT = verifier.verify(token);
            Date expiresAt = decodedJWT.getExpiresAt();
            result = expiresAt.after(new Date()) ? decodedJWT : null;
        } finally {
            return result;
        }
    }

    public static void main(String[] args) {
//        String token = generatePromotionToken(32232L, "13212120222", 1);
//        System.out.println(token);
//        String s = new JwtTokenUtil().generateToken(123);
//        System.out.println(s);
//
        DecodedJWT result = null;
        try {
//            String tokenStr =  StrUtil.sub(token, 9, token.length());
            String secret = TOKEN_KEY, issuer = TOKEN_ISSUER;
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(issuer)
                    .build();
            String s = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlzcyI6Inprai1mcG0tc3RvcmVhZG1pbiIsImV4cCI6MTYwNjc3MjQwNywiaWF0IjoxNjA2NzI5MjA3LCJ1c2VySWQiOjEyM30.VLFq7RZ8a_e6d2AXI0hS31mAbFj1T-OrZ9Ol7KNIUA8";
            DecodedJWT decodedJWT = verifier.verify(s);
            Date expiresAt = decodedJWT.getExpiresAt();
            result = expiresAt.after(new Date()) ? decodedJWT : null;
            System.out.println(result.getId());
            Map<String, Claim> claims = result.getClaims();
//            Long promotionId = claims.get("promotionId").asLong();
//            String promotionMobile = claims.get("promotionMobile").asString();
//            Integer promotionType = claims.get("promotionType").asInt();
//            System.out.println(promotionId + "_" + promotionMobile + "_" + promotionType);
        } catch (Exception e) {
        }
    }

    /**
     * 获取jwt的属性值
     *
     * @param token  token信息
     * @param pwtKey jwt的属性
     * @return jwt属性对应的值
     */
    public Integer getPropertyFromToken(String token, String pwtKey) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        return JWT.require(algorithm).build()
                .verify(token)
                .getClaim(pwtKey)
                .asInt();
    }

    public void removeToken(SysUser sysUser, DeptAllVo sysDept) {
        long currentMills = System.currentTimeMillis();
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWT.create()
                .withIssuer(issuer)
                .withIssuedAt(new Date(currentMills))
                .withClaim("userId", sysUser.getId())
                .withClaim("userName", sysUser.getUserName())
                .withClaim("userType", sysUser.getUserType())
                .withClaim("userLoginName", sysUser.getLoginName())
                .withClaim("inDustRialId", sysUser.getInDustRialId())
                .withClaim("idEntityCard", sysUser.getIdEntityCard())
                .withClaim("isVirtualUser", sysUser.getIsVirtualUser())
                .withClaim("phone", sysUser.getMobile())
                .withClaim("deptId", sysDept.getDeptid())
                .withClaim("deptCode", sysDept.getDeptcode())
                .withClaim("deptName", sysDept.getDeptname())
                .withClaim("deptLevel", sysDept.getOrgLevel())
                .withClaim("deptBizType", sysDept.getOrgBizType())
                .withClaim("fxjDeptId", sysDept.getFxjid())
                .withClaim("fxjDeptName", sysDept.getFxjname())
                .withClaim("fxjDeptCode", sysDept.getFxjcode())
                .withClaim("dszDeptId", sysDept.getDszid())
                .withClaim("dszDeptName", sysDept.getDszname())
                .withClaim("dszDeptCode", sysDept.getDszcode())
                .withIssuedAt(new Date())
                .withSubject("admin")
                //设置立马过期
                .withExpiresAt(new Date())
                .sign(algorithm);
    }
}
