package com.eactive.eai.rms.common.acl.audit.adapter.in.web;

import java.util.Map;
import java.util.StringJoiner;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.eactive.eai.rms.common.acl.audit.port.in.IsAuditableUsecase;
import com.eactive.eai.rms.common.acl.audit.port.in.SaveAuditLogUseCase;
import com.eactive.eai.rms.common.login.LoginVo;
import com.eactive.eai.rms.common.util.CommonConstants;
import com.eactive.eai.rms.common.util.IpUtil;

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

@Slf4j
@RequiredArgsConstructor
public class AuditLogInterceptor implements HandlerInterceptor {

	private final SaveAuditLogUseCase saveAuditLogUseCase;

	private final IsAuditableUsecase isAuditableUsecase;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		try {
			if (handler instanceof HandlerMethod) {
				String logType = ((HandlerMethod) handler).getBeanType().getSimpleName();
				LoginVo loginVo = (LoginVo) request.getSession().getAttribute(CommonConstants.LOGIN);
				if (loginVo != null) {
					String userId = loginVo.getUserId();
					String command = request.getParameter("cmd");
					String systemCode = request.getParameter("serviceType");
					String remoteAddress = IpUtil.getClientIp(request);

					if (isAuditableUsecase.isAuditable(userId, command, logType, systemCode)) {
						String parameters = getParametersAsString(request);
						String message = request.getParameter("auditReason");
						log
								.debug("audit log save : logType={}, cmd={}, user={}, parameters={}", logType, command,
										userId, parameters);
						saveAuditLogUseCase
								.log(systemCode, logType, command, remoteAddress, userId, parameters, message);
					}

				}
			}
		} catch (Exception e) {
			log.error("AuditLogInterceptor error", e);
		}
		return true;
	}

	private String getParametersAsString(HttpServletRequest request) {
		Map<String, String[]> parameterMap = request.getParameterMap();
		StringJoiner joiner = new StringJoiner("&");
		int totalLength = 0;
		int maxLength = 1000;

		for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
			String key = entry.getKey();
			String value = String.join(",", entry.getValue());
			String keyValue = key + "=" + value;
			int entryLength = keyValue.length();

			if (totalLength + entryLength > maxLength) {
				int remainingLength = maxLength - totalLength;
				if (remainingLength > 0) {
					joiner.add(StringUtils.substring(keyValue, 0, remainingLength));
				}
				break;
			} else {
				joiner.add(keyValue);
				totalLength += entryLength;
			}
		}

		return joiner.toString();
	}

}
