package com.inkasso.factoring.login.service.impl;

import com.auth0.jwt.interfaces.Claim;
import com.inkasso.adapter.bean.AbstractUser;
import com.inkasso.adapter.bean.Session;
import com.inkasso.adapter.constance.JwtTokenConstant;
import com.inkasso.adapter.enums.AbnormalDestoryTypeEnum;
import com.inkasso.adapter.enums.ClientTypeEnum;
import com.inkasso.adapter.util.JwtHS256Util;
import com.inkasso.adapter.util.TokenAndSessionCacheUtil;
import com.inkasso.factoring.login.model.dto.LoginResultDTO;
import com.inkasso.factoring.login.model.dto.SessionDTO;
import com.inkasso.factoring.login.service.SessionService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * @author 张超
 * @date 2021/8/6
 */
@Service
public class SessionServiceImpl implements SessionService {

    @Autowired
    private TokenAndSessionCacheUtil tokenAndSessionCacheUtil;


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public LoginResultDTO createTokenAndSession(ClientTypeEnum clientTypeEnum, AbstractUser baseUser) {
        //如果一个人管理到多个空间则baseUser里面的租户信息可能是空

        //第一步，判断用户以此种方式登陆是否已经存在过token如果存在过则需要移除以前的token
        Session session = tokenAndSessionCacheUtil.getSession(baseUser, clientTypeEnum.getCode());
        if (session == null) {
            session = new SessionDTO();
            session.setAccount(baseUser.getUserName());
        } else {
            String oldToken = session.getToken();
            AbstractUser user = tokenAndSessionCacheUtil.getLoginUserByToken(oldToken);
            if (user != null) {
                //说明旧的token有用 但是 用户重新登陆用了新的token 保存提示到redis中
                tokenAndSessionCacheUtil.setTokenAbnormalDestoryFlag(user.getUserName(),
                        AbnormalDestoryTypeEnum.REPEAT_LOGIN);
            }
            tokenAndSessionCacheUtil.removeTokenUser(oldToken);
        }
        //设置登陆时间
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String loginTime = dateTimeFormatter.format(LocalDateTime.now());
        session.setLoginTime(loginTime);
        //设置新的token
        String token = JwtHS256Util.buildJWT(clientTypeEnum, baseUser);
        session.setToken(token);
        //将token 和对应的 用户信息存在 redis 中
        tokenAndSessionCacheUtil.token2User(clientTypeEnum.getCode(), token, baseUser);
        tokenAndSessionCacheUtil.setSeeison(baseUser, clientTypeEnum.getCode(),
                session);
        LoginResultDTO loginResult = new LoginResultDTO();
        loginResult.setToken(token);
        return loginResult;
    }

    @Override
    public void resetToken2User(String token, AbstractUser baseUser) {
        tokenAndSessionCacheUtil.token2User(ClientTypeEnum.WECHAT.getCode(),token,baseUser);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void destory(String token) {
        if (Strings.isEmpty(token)) {
            return;
        }
        tokenAndSessionCacheUtil.removeTokenUser(token);
        Map<String, Claim> map = JwtHS256Util.getClaims(token);

        String account = null;

        String clientType = map.get(JwtTokenConstant.CLIENT_TYPE).asString();
        //account = map.getStringClaim(JwtTokenConstant.ACCOUNT);
        Long userId = map.get(JwtTokenConstant.USER_ID).asLong();
        if (userId != null) {
            tokenAndSessionCacheUtil.removeSessionOneType(userId, clientType, account);
        }
    }

    @Override
    public void destory(Long userId, List<String> account) {
        tokenAndSessionCacheUtil.destoryToken(userId, account);
    }

}
