package com.its.api.bis.service;

import com.its.api.bis.model.dto.BisProcessDto;
import com.its.api.bis.model.entity.BisProcess;
import com.its.api.bis.model.entity.BisProcessStatusHistory;
import com.its.api.bis.repository.BisProcessRepository;
import com.its.api.bis.repository.BisProcessStatusHistoryRepository;
import com.its.api.its.global.CodeManager;
import com.its.api.its.model.dto.unit.TbUnitSystSttsDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service
public class BisProcessService {

    private final BisProcessRepository repo;
    private final BisProcessStatusHistoryRepository sttsRepo;

    // 데이터 1건 조회, 없으면 exception
    private BisProcess requireOne(String id) {
        return this.repo.findById(id)
                .orElseThrow(() -> new NoSuchElementException("데이터가 존재하지 않습니다: " + id));
    }

    // 전체 데이터 조회
    @Transactional(readOnly = true)
    public List<BisProcessDto> findAll() {
        List<BisProcessDto> result = new ArrayList<>();
        List<BisProcess> data = this.repo.findAll();
        for (BisProcess entity : data) {
            result.add(entity.toDto());
        }
        return result;
    }

    // 데이터 1건 조회(기존 데이터가 반드시 존재해야 함)
    @Transactional(readOnly = true)
    public BisProcessDto findById(String id) {
        BisProcess entity = requireOne(id);
        return entity.toDto();
    }

    /**
     * BIS 프로세스 상태정보 조회
     * @return
     */
    @Transactional(readOnly = true)
    public List<TbUnitSystSttsDto> findAllStts() {

        Map<Integer, TbUnitSystSttsDto> result = new HashMap<>();

        Map<String, TbUnitSystSttsDto> unitMap = new HashMap<>();
        List<BisProcess> unit = this.repo.findAllList();
        unit.forEach(obj -> {
            Integer systId = obj.getProcessid();
            switch(systId) {
                case 10902: systId = 10901; break;
                case 11002: systId = 11001; break;
                case 11202: systId = 11201; break;
                case 11102: systId = 11101; break;
            }
            TbUnitSystSttsDto stts = TbUnitSystSttsDto.builder()
                    .systId(String.valueOf(systId))
                    .systNm(obj.getProcessname())
                    .systSttsCd("1")
                    .systSttsDesc("이상")
                    .updtDt(CodeManager.CMNC_STTS_ERROR_DT)
                    .runSts("1")
                    .comSts("1")
                    .dbSts("1")
                    .build();
            result.put(systId, stts);
        });

        List<BisProcessStatusHistory> sttsList = this.sttsRepo.findAllStts();
        // 실행 상태먼저 체크
        sttsList.forEach(obj -> {
            TbUnitSystSttsDto stts = result.get(obj.getProcessid());
            if (stts != null) {
                if (("4").equals(obj.getProcessstatekind())) {
                    if (("0").equals(obj.getProcessstatus())) {
                        stts.setSystSttsCd("0");
                        stts.setSystSttsDesc("정상");
                    }
                }
            }
        });
        // 실행 상태가 정상인 경우 나머지 상태정보 업데이트
        sttsList.forEach(obj -> {
            TbUnitSystSttsDto stts = result.get(obj.getProcessid());
            if (stts != null) {
                if (!("0").equals(stts.getRunSts())) {
                    return;
                }
                // 통신상태
                if (("1").equals(obj.getProcessstatekind())) {
                    if (("0").equals(obj.getProcessstatus())) {
                        stts.setComSts("0");
                    }
                }
                // DB 상태
                if (("2").equals(obj.getProcessstatekind())) {
                    if (("0").equals(obj.getProcessstatus())) {
                        stts.setDbSts("0");
                    }
                }
            }
        });
        return new ArrayList<>(result.values());
    }

}
