package com.eactive.ext.kjb.web;

import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.data.entity.onl.logger.ApiLogDTO;
import com.eactive.eai.rms.data.entity.onl.logger.ApiMessageLogDTO;
import com.eactive.eai.rms.data.entity.onl.logger.EAILogService;
import com.eactive.eai.rms.onl.apim.common.BaseRestController;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequiredArgsConstructor
public class ApiTransactionLogController extends BaseRestController {

	private final EAILogService eaiLogService;
	private final ObjectMapper objectMapper = new ObjectMapper();


	@GetMapping("/transaction/log")
	public ResponseEntity<ApiLogUI> getApiLog(String txDate,  String apiServiceNumber) {
		return getApiLog(new LogRequestBody() {{
			setTxDate(txDate);
			setApiServiceNumber(apiServiceNumber);
		}});
	}

	// 이중 매핑 문제를 해결하기 위해 (예: /api/transaction/log.do 와 /transaction/log.do) '.do' 확장자를 제거함.
	// 이제 이 엔드포인트는 /api/transaction/log 를 통해서만 접근 가능하며, API 컨벤션에 맞춰 단일하고 명확한 접근 지점을 보장함.
	@PostMapping("/transaction/log")
	public ResponseEntity<ApiLogUI> getApiLog(@RequestBody LogRequestBody requestBody) {
		DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));

		// txDate가 없으면 오늘 날짜 설정
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
		LocalDate searchDate;
		if (StringUtils.hasText(requestBody.getTxDate())) {
			searchDate = LocalDate.parse(requestBody.getTxDate(), formatter);
		} else {
			searchDate = LocalDate.now();
		}

		// 최대 10일 전까지 조회 시도
		ApiLogDTO dto = null;
		for (int i = 0; i < 10; i++) {
			String searchDateStr = searchDate.format(formatter);
			dto = eaiLogService.getApiLog(searchDateStr, requestBody.getApiServiceNumber());

			// 결과가 있으면 종료
			if (dto != null && dto.getLogs() != null && !dto.getLogs().isEmpty()) {
				break;
			}

			// 하루 전으로 이동
			searchDate = searchDate.minusDays(1);
		}

		return ResponseEntity.ok(convertToUI(dto));
	}

	private ApiLogUI convertToUI(ApiLogDTO dto) {
		ApiLogUI ui = new ApiLogUI();
		ui.setApiServiceNumber(dto.getApiServiceNumber());
		ui.setTxDate(dto.getTxDate());
		ui.setTotalProcessingTime(dto.getTotalProcessingTime());

		if (dto.getLogs() != null) {
			List<ApiMessageLogUI> uiLogs = dto.getLogs().stream().map(this::convertMessageToUI)
					.collect(Collectors.toList());
			ui.setLogs(uiLogs);
		}

		return ui;
	}

	private ApiMessageLogUI convertMessageToUI(ApiMessageLogDTO dto) {
		ApiMessageLogUI ui = new ApiMessageLogUI();
		ui.setApiServiceNumber(dto.getApiServiceNumber());
		ui.setProcessNumber(dto.getProcessNumber());
		ui.setTxDate(dto.getTxDate());
		ui.setUrl(dto.getUrl());
		ui.setQueryString(dto.getQueryString());
		ui.setClientId(dto.getClientId());
		ui.setMethod(dto.getMethod());
		ui.setHttpStatus(dto.getHttpStatus());
		ui.setExdata(dto.getExdata());
		ui.setProcessingTime(dto.getProcessingTime());
		ui.setGuid(dto.getKeymgtmsgctnt());

		// header: JSON 문자열 → Map<String, String>
		if (dto.getHeader() != null) {
			try {
				List<Map<String, String>> headerList = objectMapper.readValue(dto.getHeader(),
						new TypeReference<List<Map<String, String>>>() {
						});

				Map<String, String> headerMap = new HashMap<>();
				for (Map<String, String> headerItem : headerList) {
					String name = headerItem.get("name");
					String value = headerItem.get("value");
					if (name != null) {
						headerMap.put(name, value);
					}
				}

				// header에서 client*id 패턴 추출 (정규식, ignoreCase)
				for (Map.Entry<String, String> entry : headerMap.entrySet()) {
					if (entry.getKey() != null && entry.getKey().matches("(?i)client.*id")) {
						ui.setClientId(entry.getValue());
						break;
					}
				}

				ui.setHeader(headerMap);
			} catch (Exception e) {
				log.error("Failed to parse header JSON: {}", dto.getHeader(), e);
			}
		}

		// body: JSON 문자열 → Object
		if (dto.getBody() != null) {
			try {
				Object bodyObject = objectMapper.readValue(dto.getBody(), Object.class);
				ui.setBody(bodyObject);
			} catch (Exception e) {
				// JSON 파싱 실패 시 원본 문자열 사용
				ui.setBody(dto.getBody());
			}
		}

		return ui;
	}

	@Data
	public static class LogRequestBody {
		private String txDate;
		private String apiServiceNumber;
	}
}