package jnpf.util;

import jnpf.base.UserInfo;
import jnpf.config.ConfigValueUtil;
import jnpf.database.model.TenantVO;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.util.data.DataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.Objects;

/**
 * 租户工具类
 *
 * @author yanwenfu
 * @create 2023-11-08
 */
@Component("ftbCustomTenantUtil")
@Slf4j
public class CustomTenantUtil {

    @Autowired
    private ConfigValueUtil configValueUtil;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private AuthUtil authUtil;
    private static final String SCHEDULETASK_TOKEN = "scheduletask::fill::token::%s::%s";

    public void checkOutTenant(String tenantId) {
        if (configValueUtil.isMultiTenancy()) {
            // 判断是不是从外面直接请求
            if (StringUtil.isNotEmpty(tenantId)) {
                //切换成租户库
                try {
                    TenantDataSourceUtil.switchTenant(tenantId);
                } catch (LoginException e) {
                    // throw new RuntimeException("切换租户失败");
                    log.error("切换租户失败, 租户id: {}", tenantId);
                }
            } else {
                UserInfo userInfo = UserProvider.getUser();
                Assert.notNull(userInfo.getUserId(), "缺少租户信息");
                DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }
        }
    }

    public void checkOutTenant(String tenantId, String userId) {
        if (configValueUtil.isMultiTenancy()) {
            // 判断是不是从外面直接请求
            if (StringUtil.isNotEmpty(tenantId)) {
                TenantVO tenantVO;
                try {
                    tenantVO = TenantDataSourceUtil.getRemoteTenantInfo(tenantId);
                    TenantDataSourceUtil.switchTenant(tenantId, tenantVO);
                } catch (LoginException e1) {

                    throw new RuntimeException("切换租户失败");
                }
                if (StringUtil.isEmpty(userId)) {
                    log.error("当前切库用户为空");
                    return;
                }
                String tokenKey = String.format(SCHEDULETASK_TOKEN, tenantId, userId);
                Object tokenObj = redisTemplate.opsForValue().get(tokenKey);
                String token = Objects.isNull(tokenObj) ? null : (String) tokenObj;
                UserInfo userInfo = new UserInfo();
                userInfo.setUserId(userId);
                userInfo.setToken(token);
                userInfo.setTenantDbConnectionString(tenantVO.getDbName());
                userInfo.setAssignDataSource(DataSourceContextHolder.isAssignDataSource());
                userInfo.setTenantId(tenantId);
                if (StringUtil.isNotBlank(token) && UserProvider.isValidToken(token)) {
                    UserProvider.setLocalLoginUser(userInfo);
                    return;
                }
                try {
                    token = authUtil.loginTempUser(userId, tenantId);
                } catch (Exception e) {
                    throw new IllegalStateException("生成token失败", e);
                }
                // 检查 token 是否为空
                if (token == null || token.isEmpty()) {
                    log.error("当前用户为[{}],租户为[{}]", userId, tenantId);
                    throw new IllegalStateException("Token is empty or null");
                }
                redisTemplate.opsForValue().set(tokenKey, token);
                // 设置请求头中的 Token
                userInfo.setToken(token);
                UserProvider.setLocalLoginUser(userInfo);
            } else {
                UserInfo userInfo = UserProvider.getUser();
                Assert.notNull(userInfo.getUserId(), "缺少租户信息");
                DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }
        }
    }
}
