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;

@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();

        HashMap<String, TbDbmsSttsDto> sessionMap = new HashMap<>();
        HashMap<String, TbDbmsSttsDto> tbsMap = new HashMap<>();

        List<TbDbmsSttsDto> dbms = this.dbmsSttsMapper.findAll();
        dbms.forEach((obj) -> {
            if ("1".equals(obj.getDbSvrId()) || "2".equals(obj.getDbSvrId())) {
                sessionMap.put(obj.getDbSvrId(), obj);
            }
            else {
                tbsMap.put(obj.getTblsNm(), obj);
            }
        });

        String UPDT_DT = ItsUtils.getSysTime();
        List<SessionSttsDto> session = this.dbmsSttsMapper.findSessionUsage();
        session.forEach((obj) -> {
            String dbSvrId = String.valueOf(obj.getINST_ID());
            TbDbmsSttsDto data = sessionMap.get(dbSvrId);
            if (data != null) {
                data.setUseSesn(String.valueOf(obj.getUSE_SESN()));
                data.setUpdtDt(UPDT_DT);
            }
        });

        Double minFree = 100.0;
        Double total = 0.0;
        Double free = 0.0;

        List<TblSpaceSttsDto> tbls = this.dbmsSttsMapper.findTblsUsage();
        for (TblSpaceSttsDto obj : tbls) {
            total += obj.getTOTAL();
            free += obj.getFREE();
            if (minFree > obj.getTBLS_REMAIN_STTS()) {
                minFree = obj.getTBLS_REMAIN_STTS();
            }
            TbDbmsSttsDto data = tbsMap.get(obj.getTBLS_NM());
            if (data != null) {
                String tblsRmndCpct = String.format("%.2f", obj.getTBLS_REMAIN_STTS());
                data.setTblsRmndCpct(tblsRmndCpct);
                data.setUpdtDt(UPDT_DT);
            }
        }

        Double totalRemain = 100 - ((total - free) * 100 / total);
        String tblsRmndCpct = String.format("%.2f", totalRemain);
        TbDbmsSttsDto data1 = sessionMap.get("1");
        if (data1 != null) {
            data1.setTblsRmndCpct(tblsRmndCpct);
            data1.setUpdtDt(UPDT_DT);
        }
        //log.info("ITS DBMS: Total {}, Free {}", total[0], free[0]);

        // 결과 저장
        sessionMap.forEach((key, obj) -> {
            updateDbmsStts(obj);
        });
        tbsMap.forEach((key, obj) -> {
            updateDbmsStts(obj);
        });

        stopWatch.stop();
        long totalTimeMillis = stopWatch.getTotalTimeMillis();
        if (totalTimeMillis > 2000) {
            log.info("--END: DbmsSttsJobThread.run: {}, {} ms.", Thread.currentThread().getName(), stopWatch.getTotalTimeMillis());
        }
    }

    public void updateDbmsStts(TbDbmsSttsDto obj) {
        try {
            if (obj.getUpdtDt() == null) {
                obj.setUpdtDt(ItsUtils.getSysTime());
            }
            if (obj.getDbSvrNm() == null) {
                obj.setDbSvrNm("");
            }
            if (obj.getUseSesn() == null) {
                obj.setUseSesn("");
            }
            if (obj.getTblsRmndCpct() == null) {
                obj.setTblsRmndCpct("");
            }
            this.dbmsSttsMapper.updateDbmsStts(obj);
        } catch (Exception e) {
            log.error("Error updating: {}", obj);
        }
    }

}
