package com.its.op.scheduler.job;

import com.its.op.dao.mapper.its.dbms.DbmsSttsMapper;
import com.its.op.dto.its.dbms.SessionSttsDto;
import com.its.op.dto.its.dbms.TbDbmsSttsDto;
import com.its.op.dto.its.dbms.TblSpaceSttsDto;
import com.its.utils.ItsUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
@AllArgsConstructor
@Service
public class DbmsSttsJobThread {

    private final Environment environment;
    private final DbmsSttsMapper dbmsSttsMapper;

    @PostConstruct
    private void init() {
        log.info("{}", this);
    }

    @Async("schJobExecutor")
    public void run() {

        log.info("START: DbmsSttsJobThread.run: {}", Thread.currentThread().getName());

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        AtomicReference<String> itsMaxTblsName = new AtomicReference<>("");
        AtomicReference<String> bisMaxTblsName = new AtomicReference<>("");

        HashMap<String, TbDbmsSttsDto> dbmsMap = new HashMap<>();
        List<TbDbmsSttsDto> dbms = this.dbmsSttsMapper.findAll();
        dbms.forEach((obj) -> {
            dbmsMap.put(obj.getDbSvrId(), obj);
            if (obj.getDbSvrId().equals("2")) {
                itsMaxTblsName.set(obj.getTblsNm());
            } else if (obj.getDbSvrId().equals("4")) {
                bisMaxTblsName.set(obj.getTblsNm());
            }
        });

        String UPDT_DT = ItsUtils.getSysTime();
        List<SessionSttsDto> session = this.dbmsSttsMapper.findSessionUsage();
        session.forEach((obj) -> {
            String dbSvrId;
            if (obj.getINST_ID() == 101) {
                dbSvrId = "1";
            } else if (obj.getINST_ID() == 102) {
                dbSvrId = "2";
            } else {
                return;
            }
            TbDbmsSttsDto data = dbmsMap.get(dbSvrId);
            if (data != null) {
                data.setUseSesn(String.valueOf(obj.getUSE_SESN()));
                data.setUpdtDt(UPDT_DT);
            }
        });

        final String[] minTblsName = new String[1];
        final Double[] minFree = {100.0};
        final Double[] total = {0.0};
        final Double[] free = {0.0};

        minTblsName[0] = itsMaxTblsName.get();
        List<TblSpaceSttsDto> tbls = this.dbmsSttsMapper.findTblsUsage();
        tbls.forEach((obj) -> {
            if (obj.getTBLS_NM().contains("UNDO")) {
                return;
            }
            if (!obj.getTBLS_NM().contains("_")) {
                return;
            }
            total[0] += obj.getTOTAL();
            free[0] += obj.getFREE();
            if (minFree[0] > obj.getTBLS_REMAIN_STTS()) {
                minTblsName[0] = obj.getTBLS_NM();
                minFree[0] = obj.getTBLS_REMAIN_STTS();
            }
        });
        Double totalRemain = 100 - ((total[0] - free[0]) * 100 / total[0]);
        String tblsRmndCpct = String.format("%.2f", totalRemain);
        TbDbmsSttsDto data1 = dbmsMap.get("1");
        if (data1 != null) {
            data1.setTblsRmndCpct(tblsRmndCpct);
            data1.setUpdtDt(UPDT_DT);
        }
        TbDbmsSttsDto data2 = dbmsMap.get("2");
        if (data2 != null) {
            data2.setTblsNm(minTblsName[0]);
            data2.setTblsRmndCpct(String.valueOf(minFree[0]));
            data2.setUpdtDt(UPDT_DT);
        }
        //log.info("ITS DBMS: Total {}, Free {}", total[0], free[0]);

        // 결과 저장
//        for (Map.Entry<String, TbDbmsSttsDto> entry : dbmsMap.entrySet()) {
//            TbDbmsSttsDto obj = entry.getValue();
//            this.dbmsSttsMapper.updateDbmsStts(obj);
//        }
        dbmsMap.forEach((key, obj) -> {
            this.dbmsSttsMapper.updateDbmsStts(obj);
        });
        stopWatch.stop();
        log.info("--END: DbmsSttsJobThread.run: {}, {} ms.", Thread.currentThread().getName(), stopWatch.getTotalTimeMillis());
    }

}
