package com.its.pis.service;

import com.its.app.AppUtils;
import com.its.app.utils.SysUtils;
import com.its.pis.config.ProcessConfig;
import com.its.pis.dao.mapper.UnitSystMapper;
import com.its.pis.entity.TbUnitSyst;
import com.its.pis.entity.TbUnitSystStts;
import com.its.pis.process.AbstractDbmsJobProcess;
import com.its.pis.process.DbmsJobData;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Getter
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = {Exception.class})
public class UnitSystService {

    private final UnitSystMapper unitSystMapper;
    private final ConcurrentHashMap<String, TbUnitSyst> unitSystMap = new ConcurrentHashMap<>();
    private final TbUnitSystStts unitSystStts = TbUnitSystStts.builder().build();

    private String processId;
    private int sttsMin;
    public static String _srcIpAddr;

    @PostConstruct
    private void init() {
        log.info("[INIT...] UnitSystService.init: start.");
        ProcessConfig processConfig = (ProcessConfig) AppUtils.getBean(ProcessConfig.class);
        this.processId = processConfig.getId();

        try {
            InetAddress local = InetAddress.getLocalHost();
            String localIp = local.getHostAddress();
            long ipAddr = SysUtils.ipToLong(localIp);
            UnitSystService._srcIpAddr = String.format("%03d.%03d.%03d.%03d-", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF, (ipAddr>>8)&0xFF, (ipAddr)&0xFF);
        } catch (UnknownHostException e) {
            UnitSystService._srcIpAddr = "127.000.000.001-";
            log.error("init: UnknownHostException");
        }

        log.info("[INIT...] UnitSystService.init. _srcIpAddr: {}", UnitSystService._srcIpAddr);
        log.info("[INIT...] UnitSystService.init. processId: {}", this.processId);
        log.info("[INIT...] UnitSystService.init: ..end.");
    }

    @PreDestroy
    public void destroyService() {
        log.error("UnitSystService.destroy. system terminated.......");
        updateUnitSystStts(false);
    }

    public void loadMaster() {
        try {
            // 초기화, 기존 정보 삭제로 초기화
            for (Map.Entry<String, TbUnitSyst> e : this.unitSystMap.entrySet()) {
                e.getValue().setDEL_YN("Y");
            }

            List<TbUnitSyst> systList = this.unitSystMapper.selectAll();
            log.info("[LOADING...] UnitSystService.selectAll(), {} EA", systList.size());
            for (TbUnitSyst unit : systList) {
                if (unit.getSYST_ID().equals(this.processId)) {
                    this.unitSystStts.setSYST_ID(this.processId);
                    String localIp = unit.getSYST_IP_1().trim();
                    long ipAddr = SysUtils.ipToLong(localIp);
                    UnitSystService._srcIpAddr = String.format("%03d.%03d.%03d.%03d-", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF, (ipAddr>>8)&0xFF, (ipAddr>>0)&0xFF);
                    log.info("[LOADING...] UnitSystService.loadMaster: _srcIpAddr: {}", UnitSystService._srcIpAddr);
                }

                if (unit.getSYST_TYPE().contentEquals("UOT")) {
                    unit.setSYST_IP_1(unit.getSYST_IP_1().trim());
                    this.unitSystMap.put(unit.getSYST_ID(), unit);
                }
            }
        }
        catch (Exception e) {
            log.error("[LOADING...] UnitSystService.selectAll: Exception: {}", e.toString());
        }
    }

    public void updateUnitSystStts(boolean isRun) {
        String keyData = "unit";
        MDC.put("id", keyData);
        boolean insHs = false;
        Calendar cal = Calendar.getInstance();
        int min = cal.get(Calendar.MINUTE);
        if ((min % 5) == 0) {
            insHs = true;
            this.sttsMin = min;
        }

        String SYST_STTS_CD = isRun ? "SPS1" : "SPS3";
        this.unitSystStts.setSYST_ID(this.processId);
        this.unitSystStts.setUPDT_DT(SysUtils.getSysTime());
        this.unitSystStts.setSYST_STTS_CD(SYST_STTS_CD);

        if (!isRun) {
           this.unitSystMapper.updateUnitSystStts(this.unitSystStts);
            if (insHs) {
                this.unitSystMapper.insertUnitSystSttsHs(this.unitSystStts);
            }
        }
        else {
            AbstractDbmsJobProcess.addQ(new DbmsJobData(DbmsJobData.DATA_TYPE_UNIT_SYST_STTS, insHs, this.unitSystStts));
            if (insHs) {
                loadMaster();
            }
        }
        MDC.remove(keyData);
        MDC.clear();
    }
}
