package com.eactive.eai.rms.onl.manage.serviceinfo.itsm;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.apache.commons.collections.keyvalue.MultiKey;
import org.apache.commons.collections.map.MultiKeyMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.apim.portal.monitoringcode.entity.MonitoringCode;
import com.eactive.eai.rms.data.entity.man.monitoringCode.service.MonitoringCodeService;
import com.eactive.eai.rms.onl.common.service.EaiServerInfoService;
import com.eactive.eai.rms.onl.manage.adapter.adapter.AdapterDao;
import com.eactive.eai.rms.onl.manage.serviceinfo.itsm.vo.AdapterStatus;
import com.eactive.eai.rms.onl.server.repository.Repository;
import com.eactive.eai.rms.onl.vo.AdaptersStatusVO;

@Service
public class ItsmAdapterStatusService extends BaseService {

    private final EaiServerInfoService eaiServerInfoService;
    private final MonitoringCodeService monitoringCodeService;
    private final AdapterDao adapterDao;
    private final Repository monitorRepository;

    @Autowired
    public ItsmAdapterStatusService(EaiServerInfoService eaiServerInfoService,
                                    MonitoringCodeService monitoringCodeService,
                                    AdapterDao adapterDao,
                                    @Qualifier("repository") Repository monitorRepository) {
        this.eaiServerInfoService = eaiServerInfoService;
        this.monitoringCodeService = monitoringCodeService;
        this.adapterDao = adapterDao;
        this.monitorRepository = monitorRepository;
    }

    protected AdapterStatus getStatus() {

        try {

            return fepAdapterStatus();

        } catch (Exception e) {

            AdapterStatus error = new AdapterStatus();
            error.setErrorMsg("ERROR : " + e.getMessage());

            return error;
        }
    }

    private AdapterStatus fepAdapterStatus() throws Exception {

        MultiKeyMap adapterMap = new MultiKeyMap();

        DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.FEP));
        List<Map<String, String>> fepIpList = eaiServerInfoService.getEaiServerIpList();

        StringBuilder adapterListQuery = new StringBuilder();
        HashMap<String, String> paramMap = new HashMap<>();

        for (Map<String, String> map : fepIpList) {

            String instance = map.get("EAISVRINSTNM");
            String host = map.get("HOSTNAME");


            AdaptersStatusVO adapterVo = (AdaptersStatusVO) monitorRepository.getMonitorData(host, instance, AdaptersStatusVO.class.getName());

            if (adapterVo == null) {
                String noAdapter = "ITSM 어댑터 메모리 정보가 없습니다.";
                logger.error(noAdapter);
                throw new Exception(noAdapter);
            }

            HashMap<String, Boolean> adaptersStatus = adapterVo.getAdaptersStatus();

            adaptersStatus.forEach((adapterName, statusBoolean) -> {
                if (adapterName.contains("NET")) {

                    Map<String, Object> adapterMapValue = new HashMap<>();

                    adapterMapValue.put("status", statusBoolean);
                    adapterMap.put(instance, adapterName, adapterMapValue);

                    adapterListQuery.append("'");
                    adapterListQuery.append(adapterName);
                    adapterListQuery.append("'");
                    adapterListQuery.append(",");
                }
            });
        }

        paramMap.put("adapterList", adapterListQuery.toString().replaceAll(".$", ""));

        addMap_biz_insti_value(adapterMap, adapterDao.selectListForItsm(paramMap));

        mapping_instiName_value(adapterMap, getInstiCodeList());

        return AdapterStatus.mapping(adapterMap);
    }

    @SuppressWarnings("unchecked")
    private void addMap_biz_insti_value(MultiKeyMap adapterMap, List<HashMap<String, String>> selectListForItsm) {

        adapterMap.forEach((k, v) -> {
            String instance = ((MultiKey) k).getKey(0).toString();
            String adapterName = ((MultiKey) k).getKey(1).toString();
            HashMap<String, String> value = (HashMap<String, String>) v;

            Optional<HashMap<String, String>> adapter = selectListForItsm.stream().filter(it -> it.get("ADPTRBZWKGROUPNAME").toString().equals(adapterName)).findFirst();

            HashMap<String, String> emptyOption = adapterEmptyOption();
            String bizName = adapter.orElse(emptyOption).get("BZWKDSTICNAME");
            String instiCode = adapter.orElse(emptyOption).get("ADPTRINSTICODE");

            if (bizName == null) {
                bizName = "업무코드가 등록되어 있지 않습니다.";
            }

            value.put("bizName", bizName);
            value.put("instiCode", instiCode);
        });
    }

    private HashMap<String, String> adapterEmptyOption() {
        HashMap<String, String> emptyOption = new HashMap<>();
        emptyOption.put("BZWKDSTICNAME", "일치하는 어댑터가 존재하지 않습니다.");
        emptyOption.put("ADPTRINSTICODE", "일치하는 어댑터가 존재하지 않습니다.");
        return emptyOption;
    }

    @SuppressWarnings("unchecked")
    private void mapping_instiName_value(MultiKeyMap adapterMap, List<HashMap<String, String>> instiCodeList) {

        adapterMap.forEach((k, v) -> {
            String instance = ((MultiKey) k).getKey(0).toString();
            String adapterName = ((MultiKey) k).getKey(1).toString();
            HashMap<String, String> value = (HashMap<String, String>) v;

            Optional<HashMap<String, String>> instiCodeNameMap = instiCodeList.stream().filter(instiMap -> value.get("instiCode").equals(instiMap.get("CODE"))).findFirst();
            String instiName = instiCodeNameMap.orElse(instiEmptyOption()).get("CODENAME");
            value.put("instiName", instiName);
        });
    }

    private HashMap<String, String> instiEmptyOption() {
        HashMap<String, String> emptyOption = new HashMap<>();
        emptyOption.put("CODE", "기관매핑정보가 존재하지 않습니다.");
        emptyOption.put("CODENAME", "기관매핑정보가 존재하지 않습니다.");
        return emptyOption;
    }

    private List<HashMap<String, String>> getInstiCodeList() throws Exception {

        DataSourceContextHolder
                .setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.MONITORING));
        Iterable<MonitoringCode> monitoringCodes = monitoringCodeService.findByIdCodegroup("ADPTR_DESC");

        return StreamSupport.stream(monitoringCodes.spliterator(), false).map(code -> {
            HashMap<String, String> map = new HashMap<>();
            map.put("CODEGROUP", code.getId().getCodeGroup());
            map.put("CODE", code.getId().getCode());
            map.put("CODENAME", code.getCodeName());
            map.put("SEQ", code.getSeq().toString());
            map.put("PARENTCODEGROUP", code.getParentCodeGroup());
            map.put("PARENTCODE", code.getParentCode());
            map.put("EXT1", code.getExt1());
            map.put("EXT2", code.getExt2());
            map.put("EXT3", code.getExt3());
            map.put("EXT4", code.getExt4());
            map.put("EXT5", code.getExt5());
            map.put("USEYN", code.getUseYn());
            map.put("CREATEBY", code.getCreateBy());
            map.put("UPDATEBY", code.getUpdateBy());
            map.put("CREATEON", code.getCreateOn().toString());
            map.put("UPDATEON", code.getUpdateOn().toString());
            return map;
        }).collect(Collectors.toList());
    }

}
