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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

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 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);
            holoConfig.setConnectionMaxIdleMs(13000);
            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":"application","configurations":{"aliyun-key":"{\n\"LTAI5tGn2YicKmgcyTiJDV59\":\"iOp7cICESPZIvIjJRtTmLnCd4gT1Qy\"\n}"},"releaseKey":"20240412153514-b260f04ffbe11f4e"}
        String result = HttpUtil.get("http://proapollo.gicdev.com:7080/configs/ops_key/default/application?key=aliyun-key",10000);
        JSON json = JSONUtil.parse(result);
        String authInfo = json.getByPath("configurations.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;
    }

}
