package com.eactive.eai.rms.data.entity.onl.logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eactive.eai.data.RollingTable;
import com.eactive.eai.data.entity.onl.logger.EAILog;
import com.eactive.eai.data.entity.onl.logger.EAILogId;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraLog;
import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.data.entity.onl.apim.portalstatistics.PortalStatisticsVO;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class EAILogServiceImpl implements EAILogService {

	private final EAILogRepository eaiLogRepository;
	private final ApplicationContext applicationContext;
	private final EAILogDAOForEMS eaiLogDAOForEMS;
	private final HttpAdapterExtraLogService httpAdapterExtraLogService;

	@Override
	public Page<EAILogDto> findAll(Pageable pageable, EAILogSearch eaiLogSearch) {
		long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
		EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
		Page<EAILogDto> eaiLogDtos = eaiLogRepository.findAll(eaiLog.getClass(), pageable, eaiLogSearch);
		return eaiLogDtos;
	}

	public Map<String, Long> getTransactionCounts(EAILogSearch eaiLogSearch) {
		long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
		EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
		Map<String, Long> detailedCounts = eaiLogRepository.countDetailedTransactions(eaiLog.getClass(), eaiLogSearch);
		return detailedCounts;
	}

	@Override
	public EAILogDto getById(EAILogId eaiLogId) {
		long time = CommonUtil.getCalendar(eaiLogId.getMsgdpstyms()).getTimeInMillis();
		EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
		return eaiLogRepository.getById(eaiLog.getClass(), eaiLogId);
	}

	public List<PortalStatisticsVO> selectLogList(HashMap<String, Object> paramMap) {
		return eaiLogDAOForEMS.selectLogList(paramMap);
	}

	@Override
	public ApiLogDTO getApiLog(String txDate, String apiServiceNumber) {
		
		long time = CommonUtil.getCalendar(txDate).getTimeInMillis();
		EAILog eaiLogTargetObject = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
		List<EAILog> eaiLogs = eaiLogRepository.getApiLog(eaiLogTargetObject.getClass(), apiServiceNumber);
		eaiLogs.sort((l1, l2) -> l1.getId().getEaisvcserno().compareTo(l2.getId().getEaisvcserno()));
		
		ApiLogDTO apiLogDTO = new ApiLogDTO();
		apiLogDTO.setApiServiceNumber(apiServiceNumber);
		eaiLogs.stream().findFirst().ifPresent(log -> apiLogDTO.setTxDate(log.getId().getMsgdpstyms()));

		List<ApiMessageLogDTO> apiMessageLogDTOs = new LinkedList<>();

		for (EAILog eaiLog : eaiLogs) {
			ApiMessageLogDTO apiMessageLogDTO = new ApiMessageLogDTO();

			apiMessageLogDTO.setApiServiceNumber(apiServiceNumber);
			apiMessageLogDTO.setTxDate(eaiLog.getMsgprcssyms());
			apiMessageLogDTO.setProcessNumber(Integer.parseInt(eaiLog.getId().getLogprcssserno()));
			apiMessageLogDTO.setClientId(eaiLog.getClientid());
			apiMessageLogDTO.setKeymgtmsgctnt(eaiLog.getKeymgtmsgctnt());

			String body = StringUtils.substringAfter(eaiLog.getBzwkdatactnt(), '|');
			body = StringUtils.substringBeforeLast(body, "|");

			apiMessageLogDTO.setBody(body);
			apiMessageLogDTOs.add(apiMessageLogDTO);
		}

		Map<Integer, HttpAdapterExtraLog> extraLogs = httpAdapterExtraLogService.findByGuid(apiServiceNumber);
		for (ApiMessageLogDTO apiMessageLogDTO : apiMessageLogDTOs) {
			HttpAdapterExtraLog httpAdapterExtraLog = extraLogs.get(apiMessageLogDTO.getProcessNumber());

			if (httpAdapterExtraLog != null) {
				apiMessageLogDTO.setHeader(httpAdapterExtraLog.getHeaderContent());
				apiMessageLogDTO.setMethod(httpAdapterExtraLog.getHttpMethod());
				apiMessageLogDTO.setHttpStatus(httpAdapterExtraLog.getHttpStatus());
				apiMessageLogDTO.setUrl(httpAdapterExtraLog.getUrl());
				
				apiMessageLogDTO.setQueryString(StringUtils.substringAfter(httpAdapterExtraLog.getUrl(), "?"));
			}
		}

		// 처리 시간 계산
		for (int i = 0; i < apiMessageLogDTOs.size(); i++) {
			ApiMessageLogDTO dto = apiMessageLogDTOs.get(i);
			EAILog eaiLog = eaiLogs.get(i);

			// msgprcssyms - msgdpstyms
			long receivedTime = CommonUtil.getCalendar(eaiLog.getId().getMsgdpstyms()).getTimeInMillis();
			long processedTime = CommonUtil.getCalendar(eaiLog.getMsgprcssyms()).getTimeInMillis();
			long processingTime = processedTime - receivedTime;
			dto.setProcessingTime(processingTime);
		}

		// 전체 처리 시간 계산 (첫 수신 시각 ~ 마지막 처리 시각)
		if (!eaiLogs.isEmpty()) {
			long firstReceivedTime = CommonUtil.getCalendar(eaiLogs.get(0).getId().getMsgdpstyms()).getTimeInMillis();
			long lastProcessedTime = CommonUtil.getCalendar(eaiLogs.get(eaiLogs.size() - 1).getMsgprcssyms()).getTimeInMillis();
			long totalProcessingTime = lastProcessedTime - firstReceivedTime;
			apiLogDTO.setTotalProcessingTime(totalProcessingTime);
		}

		apiLogDTO.setLogs(apiMessageLogDTOs);
		return apiLogDTO;
	}

}
