package com.aip.gateway.api.interceptor;

import com.aip.gateway.api.entity.TbAipCallLog;
import com.aip.gateway.api.process.DbmsData;
import com.aip.gateway.api.process.DbmsDataProcess;
import com.aip.gateway.api.process.DbmsDataType;
import com.aip.gateway.api.repository.GlobalConstants;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.ContentCachingResponseWrapper;

import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.util.UUID;

@Slf4j
public class AipApiControllerInterceptor implements HandlerInterceptor {

    private final DbmsDataProcess dbmsDataProcess;
    private final ObjectMapper objectMapper;
    public AipApiControllerInterceptor(DbmsDataProcess dbmsDataProcess) {
        this.dbmsDataProcess = dbmsDataProcess;
        objectMapper = new ObjectMapper();
    }

    private String getResponseBody(HttpServletResponse response) {
        ContentCachingResponseWrapper responseWrapper = (ContentCachingResponseWrapper) response;
        byte[] contentAsByteArray = responseWrapper.getContentAsByteArray();
        try {
            return new String(contentAsByteArray, response.getCharacterEncoding());
        } catch (UnsupportedEncodingException e) {
            log.error("getResponseBody UnsupportedEncodingException: {}", e.getMessage());
            return "";
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // API GUID 생성
        String apiGuid = UUID.randomUUID().toString();
        request.setAttribute(GlobalConstants.API_GUID, apiGuid);
        request.setAttribute(GlobalConstants.API_START_TM, LocalDateTime.now());
        request.setAttribute(GlobalConstants.API_START_MILLISECONDS, System.currentTimeMillis());
        log.error("AipApiControllerInterceptor: preHandle ==> {}, {}", request.getRequestURI(), apiGuid);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 요청 처리 후 실행되는 로직 (필요한 경우 사용)
        log.error("AipApiControllerInterceptor: postHandle ==> {}", request);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 응답 완료 후 실행되는 로직 (필요한 경우 사용)
        long endTime = System.currentTimeMillis();
        long startTime = (long)request.getAttribute(GlobalConstants.API_START_MILLISECONDS);
        int errorCode = 0;
        String errorMessage = "";
        int responseStatusCode = response.getStatus();
        log.error("responseStatusCode: {}, {}", responseStatusCode, HttpStatus.OK.value());
        if (responseStatusCode != HttpStatus.OK.value()) {
            errorCode = (int)request.getAttribute(GlobalConstants.API_RESULT_CODE);
            errorMessage = (String)request.getAttribute(GlobalConstants.API_RESULT_MESSAGE);
        }

        TbAipCallLog callLog = TbAipCallLog.builder()
                .apiEndPoint(request.getRequestURI())
                .apiGuid(GlobalConstants.getApiGuid(request))
                .ipAddress((String)request.getAttribute(GlobalConstants.API_IP_ADDRESS))
                .requestAt((LocalDateTime) request.getAttribute(GlobalConstants.API_START_TM))
                .responseAt(LocalDateTime.now())
                .responseStatusCode(responseStatusCode)
                .errorCode(errorCode)
                .errorMessage(errorMessage)
                .responseTime((int)(endTime - startTime))
                .build();
        dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_API_CALL_LOG, false, callLog));

        log.error("AipApiControllerInterceptor: afterCompletion ==> {}", request.getAttribute(GlobalConstants.API_GUID));
    }

}
