package com.gic.haoban.manage.service.dao.mapper.content.holo;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.alibaba.hologres.client.HoloClient;
import com.alibaba.hologres.client.HoloConfig;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.gic.commons.util.TraceIdUtil;
import com.gic.haoban.manage.service.util.ApolloUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Author MUSI
 * @Date 2023/9/4 4:11 PM
 * @Description
 * @Version
 **/
@Slf4j
@Component
public class HoloDataSource implements InitializingBean, DisposableBean {

    private volatile HoloClient client;

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public static final String HOLO_CONNECTIONMAXIDLEMS = "holo.connectionMaxIdleMs";

    @PostConstruct
    public void initConfig() {
        Config config = ConfigService.getAppConfig();
        config.addChangeListener(this::refresh);
    }

    private void refresh(ConfigChangeEvent changeEvent) {
        if (!StringUtils.equals(changeEvent.getNamespace(), "application")) {
            return;
        }
        TraceIdUtil.traceBegin(TraceIdUtil.EntranceType.QUARTZ);
        log.info("监听刷新holo");
        ConfigChange connectionMaxIdleMsChange = changeEvent.getChange(HOLO_CONNECTIONMAXIDLEMS);
        if ((connectionMaxIdleMsChange != null && connectionMaxIdleMsChange.getNewValue() != null)) {
            init();
        }
        TraceIdUtil.traceEnd();
    }

    public synchronized void init() {
        try {
            Config appConfig = ConfigService.getAppConfig();
            String holoUrl = appConfig.getProperty("holo.url", "");
            Pair<String, String> holoAuth = getHoloAuth();
            if (holoAuth == null) {
                log.info("holo链接初始化获取授权信息失败");
                return;
            }
            String holoUserName = holoAuth.getKey();
            String holoPassword = holoAuth.getValue();
            HoloConfig holoConfig = new HoloConfig();
            holoConfig.setJdbcUrl(holoUrl);
            holoConfig.setUsername(holoUserName);
            holoConfig.setPassword(holoPassword);
            log.info("holo链接初始化,holoUrl:{},holoUserName:{},holoPassword:{}",holoUrl,holoUserName,holoPassword);
            holoConfig.setConnectionMaxIdleMs(ApolloUtils.connectionMaxIdleMs());
            HoloClient newClient = new HoloClient(holoConfig);
            newClient.setAsyncCommit(false);
            if (this.client != null) {
                this.client.close();
                this.client = null;
            }
            this.client = newClient;
            log.info("holo链接初始化完成");
        }catch (Exception ex) {
            log.info("初始化client 异常 >>>", ex);
        }
    }

    @Override
    public void destroy() throws Exception {
        if (client != null) {
            client.close();
        }
        scheduler.shutdown();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (client == null) {
            this.init();
        }
        DateTime now = DateUtil.date();
        Date todayTwo = DateUtil.beginOfDay(now).offset(DateField.HOUR_OF_DAY, 2);
        if (now.after(todayTwo)) {
            todayTwo = DateUtil.offsetDay(todayTwo, 1);
        }
        scheduler.scheduleAtFixedRate(this::reinitialize, DateUtil.between(now,todayTwo, DateUnit.SECOND,true), 24 * 60 * 60, TimeUnit.SECONDS);
    }


    public HoloClient getClient() {
        if (this.client == null) {
            synchronized (this) {
                if (this.client == null) {
                    this.init();
                }
            }
        }
        return this.client;
    }

    // 重新初始化方法
    public synchronized void reinitialize() {
        this.init();
    }

    private Pair<String, String> getHoloAuth() {
        //{"appId":"ops_key","cluster":"default","namespaceName":"key_config","configurations":{"demo_aliyun_key":"{\n    \"LTAI5tMF2pZGShdULEYbyntc\": \"pC16FjCeklpXg18duNhJsEF91FvxpE\"\n}"},"releaseKey":"20240604165817-7632f04ffbe11f53"}
        String result = HttpUtil.get("http://10.0.100.2:7080/configs/ops_key/default/key_config",10000);
        JSON json = JSONUtil.parse(result);
        String authInfo = json.getByPath("configurations.demo_aliyun_key", String.class);
        JSON authJson = JSONUtil.parseObj(authInfo);
        Map<String, String> map = authJson.toBean(new TypeReference<Map<String, String>>() {});
        for (Map.Entry<String, String> entry : map.entrySet()) {
            return new Pair<>(entry.getKey(), entry.getValue());
        }
        return null;
    }

}
