package com.its.api.its.service.report;

import com.its.api.its.global.CodeManager;
import com.its.api.its.model.dto.report.*;
import com.its.api.its.model.entity.cctv.TbCctvSttsHs;
import com.its.api.its.model.entity.incident.TbIncdOcrr;
import com.its.api.its.model.entity.link.TbLinkTrafHs;
import com.its.api.its.model.entity.vds.TbVdsCtlrSttsHs;
import com.its.api.its.model.entity.vms.TbVmsSttsHs;
import com.its.api.its.repository.cctv.TbCctvSttsHsRepository;
import com.its.api.its.repository.incident.TbIncdOcrrRepository;
import com.its.api.its.repository.link.TbLinkTrafHsRepository;
import com.its.api.its.repository.vds.TbVdsCtlrSttsHsRepository;
import com.its.api.its.repository.vms.TbVmsSttsHsRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class ReportService {

    private final TbCctvSttsHsRepository cctvSttsHsRepo;
    private final TbVmsSttsHsRepository vmsSttsHsRepo;
    private final TbVdsCtlrSttsHsRepository vdsSttsHsRepo;
    private final TbIncdOcrrRepository incdOcrrRepo;
    private final TbLinkTrafHsRepository linkTrafHsRepo;

    /**
     * 보고서 - 시설물 보고서 - 시설물 현황
     * @param fromDt
     * @param toDt
     * @return
     */
    @Transactional(readOnly = true)
    public List<ReportFacilitySummaryDto> findAllFacilitySummary(String fromDt, String toDt){

        List<ReportFacilitySummaryDto> result = new ArrayList<>();

        ReportFcltSummaryInf cctvSummary = this.cctvSttsHsRepo.findAllReportSummary(fromDt, toDt);
        result.add(ReportFacilitySummaryDto.builder()
                .fcltSeq(1)
                .fcltType("CCTV")
                .cms0Cnt(cctvSummary.getCms0Cnt().intValue())
                .cms1Cnt(cctvSummary.getCms1Cnt().intValue())
                .build());

        ReportFcltSummaryInf vmsSummary = this.vmsSttsHsRepo.findAllReportSummary(fromDt, toDt);
        result.add(ReportFacilitySummaryDto.builder()
                .fcltSeq(2)
                .fcltType("VMS")
                .cms0Cnt(vmsSummary.getCms0Cnt().intValue())
                .cms1Cnt(vmsSummary.getCms1Cnt().intValue())
                .build());

        ReportFcltSummaryInf vdsSummary = this.vdsSttsHsRepo.findAllReportSummary(fromDt, toDt);
        result.add(ReportFacilitySummaryDto.builder()
                .fcltSeq(3)
                .fcltType("VDS")
                .cms0Cnt(vdsSummary.getCms0Cnt().intValue())
                .cms1Cnt(vdsSummary.getCms1Cnt().intValue())
                .build());

        return result;
    }

    /**
     * 보고서 - 시설물 보고서 - 장애 현황
     * @param fromDt
     * @param toDt
     * @return
     */
    @Transactional(readOnly = true)
    public List<ReportFacilityErrorDto> findAllFacilityError(String fromDt, String toDt){

        List<ReportFacilityErrorDto> result = new ArrayList<>();

        List<TbCctvSttsHs> cctvError = this.cctvSttsHsRepo.findAllReportError(fromDt, toDt);
        cctvError.forEach(obj -> {
            result.add(ReportFacilityErrorDto.builder()
                    .fcltSeq(1)
                    .fcltType("CCTV")
                    .fcltId(obj.getCctv() != null ? obj.getCctv().getCctvCtlrId() : String.valueOf(obj.getCctvMngmNmbr()))
                    .fcltNm(obj.getCctv() != null ? obj.getCctv().getIstlLctnNm() : String.valueOf(obj.getCctvMngmNmbr()))
                    .rgstDt(obj.getCrtnDt())
                    .build());
        });


        List<TbVmsSttsHs>  vmsError = this.vmsSttsHsRepo.findAllReportError(fromDt, toDt);
        vmsError.forEach(obj -> {
            result.add(ReportFacilityErrorDto.builder()
                    .fcltSeq(2)
                    .fcltType("VMS")
                    .fcltId(obj.getVms() != null ? obj.getVms().getVmsCtlrId() : String.valueOf(obj.getVmsCtlrNmbr()))
                    .fcltNm(obj.getVms() != null ? obj.getVms().getVmsNm() : String.valueOf(obj.getVmsCtlrNmbr()))
                    .rgstDt(obj.getRgstDt()).build());
        });

        List<TbVdsCtlrSttsHs>  vdsError = this.vdsSttsHsRepo.findAllReportError(fromDt, toDt);
        vdsError.forEach(obj -> {
            result.add(ReportFacilityErrorDto.builder()
                    .fcltSeq(3)
                    .fcltType("VDS")
                    .fcltId(obj.getVds() != null ? obj.getVds().getVdsCtlrId() : obj.getCtlrMngmNmbr())
                    .fcltNm(obj.getVds() != null ? obj.getVds().getLctn() : obj.getCtlrMngmNmbr())
                    .rgstDt(obj.getOcrrDt())
                    .build());
        });

        return result;
    }

    /**
     * 보고서 - 교통 보고서 - 돌발 현황(진행중 돌발)
     * @param fromDt
     * @param toDt
     * @return
     */
    @Transactional(readOnly = true)
    public List<ReportTrafficIncidentDto> findAllTrafficIncident(String fromDt, String toDt){

        List<ReportTrafficIncidentDto> result = new ArrayList<>();

        CodeManager.loadCode(CodeManager.INCD_CODE_IDTU);

        List<TbIncdOcrr> data = this.incdOcrrRepo.findAllProgressIncidentByDateRange(fromDt, toDt);
        data.forEach(obj -> {
            result.add(ReportTrafficIncidentDto.builder()
                    .incdStrtDt(obj.getIncdStrtDt())
                    .cmmnCdKorNm(CodeManager.getCodeDescShort(CodeManager.INCD_CODE_IDTU, obj.getIncdTypeCd()))
                    .linkId(String.valueOf(obj.getLinkId()))
                    .incdTitl(obj.getIncdTitl()).build());
        });
        return result;
    }

    /**
     * 보고서 - 교통 보고서 - 정체 현황
     * @param fromDt
     * @param toDt
     * @return
     */
    @Transactional(readOnly = true)
    public List<ReportTrafficCongestDto> findAllTrafficCongest(String fromDt, String toDt) {

        List<ReportTrafficCongestDto> result = new ArrayList<>();
        List<TbLinkTrafHs> data = this.linkTrafHsRepo.findAllCongestByDateRange(fromDt, toDt);
        data.forEach(obj -> {
            result.add(ReportTrafficCongestDto.builder()
                    .linkId(String.valueOf(obj.getLinkId()))
                    .prcnDt(obj.getPrcnDt())
                    .cmtrGradCd(obj.getCmtrGradCd())
                    .sped(obj.getSped())
                    .build());
        });
        return result;
    }

}
