package com.utic.center.utic.stat.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.stat.server.dao.repository.UticStatPatternRepository;
import com.utic.center.utic.stat.server.dto.CodeValueDto;
import com.utic.center.utic.stat.server.dto.HolidayDto;
import com.utic.center.utic.stat.server.dto.PatternDto;
import com.utic.center.utic.stat.server.dto.PatternJobDto;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Getter
@RequiredArgsConstructor
@Service
public class UticStatPatternService implements AbstractProcessService {

    private final UticStatParamService paramService;
    private final UticStatPatternRepository patternRepo;

    @ProcessingElapsed(type="1HOUR", name="정주기 1시간 패턴초기화", starting = false)
    @Override
    public boolean processing() {
        PatternDto pattern = this.patternRepo.findPatternDay();
        if (pattern == null) {
            return false;
        }

        log.info("[INF] {}: patternExeDay[{}], weekDay[{}], workWeek[1,2]", LogUtils.elapsedLog("PATTERN"),
                pattern.getExeDay(), pattern.getWeekDay());

        // 패턴작업을 위한 작업 테이블 초기화 수행
        // 1. 매시 정각에 수행
        // 2. 시스템의 현재일자 요일을 구한다.
        // 3. 일요일 이면 5분 패턴 작업 테이블을 초기화 한다.
        // 4. 월요일 이면 15분 패턴 작업 테이블을 초기화 한다.
        // 5. 작업을 수행할때 현재일자와 코드명으로 데이터를 입력.
        // 6. 작업완료후에 현재일자와 코드명으로 데이터를 업데이트.

        // 1:일,2:월,3:화,4:수,5:목,6:금,7:토
        if (pattern.getWeekDay() == 1) {
            // 05분 패턴작업 테이블 초기화
            patternInitialize("0", pattern.getExeDay());
        }
        else if (pattern.getWeekDay() == 2) {
            // 15분 패턴작업 테이블 초기화
            patternInitialize("1", pattern.getExeDay());
        }
        return true;
    }

    private void patternInitialize(String patternType, String exeDay) {
        PatternJobDto patternJobLog = this.patternRepo.findPatternJobLog(patternType, exeDay);
        if (patternJobLog == null || patternJobLog.getJobCount() >= 1) {
            // 데이터가 존재하면 이미 작업을 수행했음
            return;
        }

        // 패턴작업 테이블 로그 입력
        this.patternRepo.insertPatternJobLog(patternType, exeDay);

        // Delete existing pattern week job
        if ("0".equals(patternType)) {
            this.patternRepo.deletePatternWeekJob();
        }
        else {
            this.patternRepo.deletePattern15MinWeekJob();
        }

        // 패턴작업 테이블 로그 업데이트
        this.patternRepo.updatePatternJobLog(patternType, exeDay);
    }

    public void patternUpdate(String patternTime, boolean is05Min) {
        final String tablePrifix = is05Min ? "PATN_" : "PATN_15MIN_";
        String logTable, fromTable;
        String minValue = "0";
        String maxValue = "0";
        String columnName = "SPEED3";

        CodeValueDto code11 = this.paramService.getCodeValue(UticStatParamService.CodeValueKey.CODE_11);
        CodeValueDto code12 = this.paramService.getCodeValue(UticStatParamService.CodeValueKey.CODE_12);
        CodeValueDto code13 = this.paramService.getCodeValue(UticStatParamService.CodeValueKey.CODE_13);
        CodeValueDto code14 = this.paramService.getCodeValue(UticStatParamService.CodeValueKey.CODE_14);
        CodeValueDto code15 = this.paramService.getCodeValue(UticStatParamService.CodeValueKey.CODE_15);
        CodeValueDto code16 = this.paramService.getCodeValue(UticStatParamService.CodeValueKey.CODE_16);

        boolean isWeek = false;
        HolidayDto holiday = null;
        holiday = this.patternRepo.findHoliday(patternTime);
        if (holiday == null) {
            log.error("[ERR] {}, findHoliday[{}], {} 휴일정보가 없습니다.", LogUtils.elapsedLog("HOLIDAY"), patternTime, is05Min ? "05MIN" : "15MIN");
            return;
        }

        if (holiday.getHCnt() > 0) {
            logTable = tablePrifix + "HOLIDAY(휴일)";
            fromTable = tablePrifix + "HOLIDAY";
            minValue = String.valueOf(code16.getMinValue());
            maxValue = String.valueOf(code16.getMaxValue());
        }
        else {
            switch(holiday.getWDay()) {
                case 1: // 일요일 패턴
                    logTable = tablePrifix + "SUN(일요일)";
                    fromTable = tablePrifix + "SUN";
                    minValue = String.valueOf(code11.getMinValue());
                    maxValue = String.valueOf(code11.getMaxValue());
                    break;
                case 2: // 월요일 패턴
                    logTable = tablePrifix + "MON(월요일)";
                    fromTable = tablePrifix + "MON";
                    minValue = String.valueOf(code12.getMinValue());
                    maxValue = String.valueOf(code12.getMaxValue());
                    break;
                case 6: // 금요일 패턴
                    logTable = tablePrifix + "FRI(금요일)";
                    fromTable = tablePrifix + "FRI";
                    minValue = String.valueOf(code14.getMinValue());
                    maxValue = String.valueOf(code14.getMaxValue());
                    break;
                case 7: // 토요일 패턴
                    logTable = tablePrifix + "SAT(토요일)";
                    fromTable = tablePrifix + "SAT";
                    minValue = String.valueOf(code15.getMinValue());
                    maxValue = String.valueOf(code15.getMaxValue());
                    break;
                default: // 평일 패턴(3,4,5)
                    isWeek = true;
                    logTable = tablePrifix + "WEEK(평일)";
                    fromTable = tablePrifix + "WEEK";
                    if (holiday.getWDay() == 3) {
                        columnName = "SPEED3";
                    }
                    else if (holiday.getWDay() == 4) {
                        columnName = "SPEED4";
                    }
                    else {
                        columnName = "SPEED5";
                    }
                    break;
            }
        }

        // 패턴이력저장
        this.patternRepo.insertPatternHist(fromTable + "_HIST", fromTable, patternTime, logTable);

        final String targetTable = is05Min ? "PATN_WEEK_JOB"    : "PATN_15MIN_WEEK_JOB";
        final String statTable   = is05Min ? "STAT_5MIN_CENTER" : "STAT_15MIN_CENTER";
        final String mergeTable  = is05Min ? "PATN_WEEK"        : "PATN_15MIN_WEEK";
        if (isWeek) {
            // 평일(3,4,5)
            // 패턴 작업 테이블 업데이트
            this.patternRepo.mergePatternWeekJob(targetTable, statTable, columnName, patternTime, holiday.getWDay().toString());
        }
        else {
            this.patternRepo.updatePattern(fromTable, statTable, patternTime, minValue, maxValue, logTable);
        }

        if (holiday.getWDay() == 6) {
            // 금요일 이면 금요일 패턴을 업데이트 하고(위에서 처리) 평일패턴을 업데이트 한다.
            // 평일패턴작업 테이블을 이용하여 작업을 수행한다.
            minValue = String.valueOf(code13.getMinValue());
            maxValue = String.valueOf(code13.getMaxValue());
            this.patternRepo.mergePatternWeek(mergeTable, targetTable, patternTime, minValue, maxValue);
        }
    }

}
