package com.njzscloud.supervisory.auth.service;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.common.core.fastjson.Fastjson;
import com.njzscloud.common.security.contant.Constants;
import com.njzscloud.common.security.support.ITokenService;
import com.njzscloud.common.security.support.Token;
import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.supervisory.auth.mapper.SysTokenMapper;
import com.njzscloud.supervisory.auth.pojo.SysTokenEntity;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class TokenService implements ITokenService {
    private static final TimedCache<Long, UserDetail> TOKEN_CACHE = CacheUtil.newTimedCache(1000 * 3600);
    private final SysTokenMapper sysTokenMapper;

    @Override
    public synchronized void saveToken(UserDetail userDetail) {
        Token token = userDetail.getToken();
        long userId = token.getUserId();
        String tid = token.getTid();
        String key = Constants.TOKEN_CACHE_KEY.fill(userId, tid);
        Long l = sysTokenMapper.selectCount(Wrappers.<SysTokenEntity>lambdaQuery().eq(SysTokenEntity::getUserId, token.getUserId()));
        if (l > 0) return;
        sysTokenMapper.insert(new SysTokenEntity()
                .setUserId(userId)
                .setTid(tid)
                .setTkey(key)
                .setTval(token.toString())
                .setUserDetail(userDetail.toString())
        );
    }

    @Override
    public UserDetail loadUser(String tokenStr) {
        Token token = Token.create(tokenStr);
        long userId = token.getUserId();
        return TOKEN_CACHE.get(userId, () -> Fastjson.toBean(sysTokenMapper
                        .selectOne(Wrappers.<SysTokenEntity>lambdaQuery()
                                .eq(SysTokenEntity::getUserId, userId))
                        .getUserDetail(),
                UserDetail.class));
    }

    @Override
    public void removeToken(Token token) {
        long userId = token.getUserId();
        TOKEN_CACHE.remove(userId);
        sysTokenMapper.delete(Wrappers.<SysTokenEntity>lambdaQuery()
                .eq(SysTokenEntity::getUserId, userId)
        );
        TOKEN_CACHE.remove(userId);
    }

    @Override
    public void removeToken(Long userId) {
        TOKEN_CACHE.remove(userId);
        sysTokenMapper.delete(Wrappers.<SysTokenEntity>lambdaQuery()
                .eq(SysTokenEntity::getUserId, userId)
        );
        TOKEN_CACHE.remove(userId);
    }
}
