package com.samsung.interceptor;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import com.fasterxml.jackson.databind.ObjectMapper;

@Intercepts({
		@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
				RowBounds.class, ResultHandler.class }),
		@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisExecuteInterceptor implements Interceptor {
	private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MybatisExecuteInterceptor.class);

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StringBuilder str = new StringBuilder();
		String queryID = ((MappedStatement) invocation.getArgs()[0]).getId();
		str.append("QUERYID ==================>>> ");
		str.append(queryID);
		str.append(" <<<==================\n");
		
		Object param = invocation.getArgs()[1];
		ObjectMapper mapper = new ObjectMapper();
		str.append(mapper.writeValueAsString(param));
				
		log.info(str.toString());

		

		

		//BoundSql boundSql = ((MappedStatement) invocation.getArgs()[0]).getBoundSql(param);
		//String queryString = boundSql.getSql();

		//str.append("\n=========================== 쿼리검증 ==============================\n");
		//if (queryID.indexOf("clms") > -1 &&  queryString.indexOf("2024#LAS 전환확인") < 0) str.append("====> 쿼리전환작업대상  <====\n");
		//str.append(queryID);
		//str.append("\n=========================================================\n");

		//log.info(queryString);
		
		/*

		Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@10.155.21.158:1621:LAS", "las",
				"dlatl003!");

		try {
			PreparedStatement ps = conn.prepareStatement(
					"INSERT INTO ZZ_CLM_QUERY_LOG ( SID,QUERY_ID,QUERY ) VALUES ( zz_seq.NEXTVAL, '" + queryID + "',? )");

			((OraclePreparedStatement) ps).setStringForClob(1, queryString.replaceAll("(?m)^[ \t]*\r?\n", ""));
			ps.execute();
		}
		finally {
			conn.close();
		}*/

		return invocation.proceed();
	}

	private Object getObject(Object parameterObject, ParameterMapping parameterMapping, BoundSql boundSql)
			throws IllegalAccessException, NoSuchFieldException {
		if (parameterObject instanceof Number || parameterObject instanceof String)
			return parameterObject;
		else if (parameterObject instanceof Map) {

			String propKey = parameterMapping.getProperty(); // <foreach>인 경우 propKey가 "__frch_%아이템명%_반복횟수"
			Object value = ((Map<?, ?>) parameterObject).get(propKey);
			if (value == null) {
				// __frch_ PREFIX에 대한 처리
				if (boundSql.hasAdditionalParameter(propKey)) { // myBatis가 추가 동적인수를 생성했는지 체크하고
					value = boundSql.getAdditionalParameter(propKey); // 해당 추가 동적인수의 Value를 가져옴
					return value;
				}
			}
			return value;

			// String property = parameterMapping.getProperty();
			// return ((Map<?, ?>) parameterObject).get(property);
		} else {
			Class<?> aClass = parameterObject.getClass();
			String property = parameterMapping.getProperty();
			Field declaredField = null;
			try {
				declaredField = aClass.getDeclaredField(property);
			} catch (NoSuchFieldException e) {
				while (aClass.getSuperclass() != null) {
					aClass = aClass.getSuperclass();
					try {
						declaredField = aClass.getDeclaredField(property);
						break;
					} catch (NoSuchFieldException ignored) {
					}
				}
			}

			if (declaredField == null)
				throw new NoSuchFieldException(property);

			declaredField.setAccessible(true);
			return declaredField.get(parameterObject);
		}
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
	}
}