package com.utic.center.utic.traf.server.service;

import com.utic.center.common.annotation.ProcessingElapsed;
import com.utic.center.common.service.AbstractProcessService;
import com.utic.center.common.utils.LogUtils;
import com.utic.center.utic.traf.server.config.TraceConfig;
import com.utic.center.utic.traf.server.dao.repository.utic.AsnDbRepository;
import com.utic.center.utic.traf.server.dao.repository.utic.UticTrafficRepository;
import com.utic.center.utic.traf.server.dto.AsnCenterDto;
import com.utic.center.utic.traf.server.dto.AsnCollectInfoDto;
import com.utic.center.utic.traf.server.repository.ApplicationRepository;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Data
@ToString
@RequiredArgsConstructor
@Service
public class LinkTrafAsnService implements AbstractProcessService {

    private final TraceConfig trace;
    private final UticTrafficRepository uticRepo;
    private final AsnDbRepository asnDbRepo;
    private final ConcurrentHashMap<String, AsnCenterDto> centerMap = new ConcurrentHashMap<>();
    private volatile boolean loadCenter = false;

    @PostConstruct
    void init() {
        loadCenterInfo();
    }

    private void loadCenterInfo() {
        // 1. 센터정보 조회
        List<AsnCenterDto> asnCenters = this.asnDbRepo.findAllAsnCenter();
        for (AsnCenterDto dto : asnCenters) {
            this.centerMap.put(dto.getCenterId(), dto);
        }
    }

    @ProcessingElapsed(type="@ASNDB", name="ASN 소통정보 이관", starting = false, endLine = true)
    @Override
    public boolean processing() {
        // 1. 센터정보 조회
        if (this.loadCenter) {
            loadCenterInfo();
            this.loadCenter = false;
        }

        // 2. 교통정보테이블 초기화
//        this.uticRepo.truncateTrafficLoc();

        // 3. 교통정보 입력
        this.asnDbRepo.insertTrafficLoc(ApplicationRepository.trafPrcsTime);

        // 4. 돌발정보 입력
        this.asnDbRepo.insertIncidentCommon(ApplicationRepository.trafPrcsTime);

        if (this.trace.isDebug()) {
            // 디버그 모드일 경우에만 센터별 교통정보 수집정보를 조회하여 로그 출력
            // 5. 센터별 교통정보 수집
            List<AsnCollectInfoDto> asnCollectInfos = this.asnDbRepo.findAllTrafficLocCount(ApplicationRepository.trafPrcsTime);
            if (asnCollectInfos == null) {
                log.warn("[WAN] {}: asnCollectInfos is null.", LogUtils.elapsedLog("asnTrafficDataProcess"));
                return false;
            }

            for (AsnCollectInfoDto clct : asnCollectInfos) {
                AsnCenterDto center = this.centerMap.get(clct.getCenterId());
                if (center != null) {
                    center.setDataCount(clct.getDataCount());
                }
                else {
                    center = new AsnCenterDto(clct.getCenterId(), clct.getCenterId(), clct.getDataCount());
                    this.centerMap.put(center.getCenterId(), center);
                    this.loadCenter = true;
                }
            }

            this.centerMap.values().stream()
                    .filter(dto -> dto.getDataCount() > 0)
                    .sorted(Comparator.comparing(AsnCenterDto::getCenterId))
                    .forEach(dto -> {
                        log.info("[INF] {}: {}, {} EA.",
                                LogUtils.elapsedLog(dto.getCenterInfo()), dto.getCenterId(), LogUtils.numberLog(dto.getDataCount()));
                    });
        }
        return true;
    }
}
