package com.its.vds.service;

import com.its.app.AppUtils;
import com.its.app.utils.Elapsed;
import com.its.app.utils.SysUtils;
import com.its.vds.config.ApplicationConfig;
import com.its.vds.dao.mapper.VdsCtlrMapper;
import com.its.vds.domain.NET;
import com.its.vds.dto.TbVdsCtlrDto;
import com.its.vds.entity.TbVdsCtlr;
import com.its.vds.entity.TbVdsCtlrStts;
import com.its.vds.process.DbmsData;
import com.its.vds.process.DbmsDataProcess;
import com.its.vds.process.DbmsDataType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;

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

    private final ApplicationConfig config;
    private final AppRepositoryService repoService;
    private final VdsCtlrMapper mapper;
    private int historyMin;

    @PostConstruct
    private void init() {
        log.info("VdsCtlrService.init: Start.");
        this.historyMin = -1;
        log.info("VdsCtlrService.init: ..End.");
    }

    public void loadDb() {
        loadCtlrInfo();
        loadCtlrSttsInfo();
    }

    public void loadCtlrInfo() {
        Elapsed elapsed = new Elapsed();
        this.repoService.initCtlrInfo();

        try {
            List<TbVdsCtlr> infoList  = this.mapper.selectAll();
            log.info("VdsCtlrService.loadCtlrInfo: {} EA", infoList.size());
            for (TbVdsCtlr dto : infoList) {
                log.info("VdsCtlrService.loadCtlrInfo: {}.", dto);
                TbVdsCtlrDto vdsObj = dto.toDto();
                if (vdsObj.getVdsCtlrId().trim().equals("")) {
                    log.error("VdsCtlrService.loadCtlrInfo: Controller Ip Address Error: {}.", vdsObj);
                    continue;
                }

                this.repoService.putCtlrMap(vdsObj);
                this.repoService.putIpAddrMap(vdsObj);
                vdsObj.getStts().initUnknown();
            }
        }
        catch (Exception e) {
            log.error("VdsCtlrService.loadCtlrInfo: {}.", e.toString());
        }

        this.repoService.getCtlrMap().forEach((key, obj) -> {
            log.info("VdsCtlrService.loadCtlrInfo:: {}.", obj.toString());
        });
        log.info("VdsCtlrService.loadCtlrInfo: {} ms.", elapsed.milliSeconds());
    }

    public void loadCtlrSttsInfo() {
        Elapsed elapsed = new Elapsed();
        try {
            List<TbVdsCtlrStts> infoList  = this.mapper.selectVdsCtlrStts();
            log.info("VdsCtlrService.loadCtlrSttsInfo: {} EA", infoList.size());
            infoList.forEach(dto -> {
                TbVdsCtlrDto obj = this.repoService.getCtlrMap(dto.getVdsCtlrNmbr());
                if (obj == null) {
                    log.error("VdsCtlrService.loadCtlrSttsInfo: Not Found VDS {}.", dto.getVdsCtlrNmbr());
                    return;
                }
                obj.getStts().updateStts(dto);
            });
        }
        catch (Exception e) {
            log.error("VdsCtlrService.loadCtlrSttsInfo: {}.", e.toString());
        }
        log.info("VdsCtlrService.loadCtlrSttsInfo: {} ms.", elapsed.milliSeconds());
    }

    public void updateCtlrStts(boolean isRun, TbVdsCtlrDto AObj) {
        boolean insHs = false;
        Calendar cal = Calendar.getInstance();
        int min = cal.get(Calendar.MINUTE);
        if (((min % 5) == 0) && this.historyMin != min) {
            insHs = true;
            this.historyMin = min;
        }

        //제어기 상태정보 업데이트
        List<TbVdsCtlrStts> ctlrSttsList = Collections.synchronizedList(new ArrayList<>());
        String UPDT_DT = SysUtils.getSysTime();
        int normal = 0;
        int error  = 0;

        for (Map.Entry<Long, TbVdsCtlrDto> e : this.repoService.getCtlrMap().entrySet()) {
            TbVdsCtlrDto obj = e.getValue();
            if (AObj != null && !Objects.equals(AObj.getVdsCtlrNmbr(), obj.getVdsCtlrNmbr())) {
                continue;
            }

            obj.getStts().setUpdtDt(UPDT_DT);
            if (isRun && obj.getNetState() >= NET.LOGINED && obj.getChannel() != null) {
                //제어기 통신정상
                normal++;
                obj.getStts().setCmncSttsCd("CMS0");
            }
            else {
                //제어기 통신이상
                error++;
                obj.getStts().initError();
            }

            if (isRun) {
                ctlrSttsList.add(obj.getStts());
            }
            else {
                this.mapper.updateVdsCtlrStts(obj.getStts());
                if (insHs) {
                    this.mapper.insertVdsCtlrSttsHs(obj.getStts());
                }
            }
        }

        // 제어기 상태정보 DB 업데이트
        if (!ctlrSttsList.isEmpty()) {
            DbmsDataProcess dbmsDataProcess = (DbmsDataProcess) AppUtils.getBean(DbmsDataProcess.class);
            dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_CTLR_STTS_LIST, insHs, ctlrSttsList));
        }

        log.info("VdsCtlrService.updateCtlrStts: total {}, normal {}, error {}.", normal + error, normal, error);
    }

}
