package incheon.com.config.mybatis;

import incheon.com.cmm.context.RequestContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Map;
import java.util.Properties;

/**
 * MyBatis SQL 실행 시 자동으로 현재 인증된 사용자 ID를 파라미터에 주입하는 인터셉터
 *
 * RequestContext에서 사용자 정보를 가져와 MyBatis 쿼리에 자동으로 주입합니다.
 *
 * - INSERT/UPDATE/DELETE 쿼리: LOGIN_USER_ID 파라미터로 사용자 ID 주입
 * - Map 파라미터: LOGIN_USER_ID 키로 주입
 * - ComDefaultVO 파라미터: LOGIN_USER_ID 필드로 주입
 */
@Intercepts({
    @Signature(type = Executor.class, method = "update", 
               args = {MappedStatement.class, Object.class}),
    @Signature(type = Executor.class, method = "query", 
               args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MybatisUserSessionInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object param = args[1];

        // 모든 SQL 작업에 세션 정보 추가 (SELECT 포함)
        if (ms.getSqlCommandType() == SqlCommandType.INSERT ||
            ms.getSqlCommandType() == SqlCommandType.UPDATE ||
            ms.getSqlCommandType() == SqlCommandType.DELETE ||
            ms.getSqlCommandType() == SqlCommandType.SELECT) {

            // RequestContext에서 현재 인증된 사용자 정보 가져오기
            String userId = RequestContext.getCurrentUserId();

            // userId가 null인 경우 기본값 설정
            if (userId == null) {
                userId = "ANONYMOUS";
            }

            // 파라미터가 Map인 경우
            if (param instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> paramMap = (Map<String, Object>) param;
                paramMap.put("LOGIN_USER_ID", userId);
            }
            // 파라미터가 ComDefaultVO 또는 그 하위 클래스인 경우
            else if (param instanceof incheon.com.cmm.ComDefaultVO) {
                incheon.com.cmm.ComDefaultVO vo = (incheon.com.cmm.ComDefaultVO) param;
                vo.setLOGIN_USER_ID(userId);
            }
        }

        return invocation.proceed();
    }

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

    @Override
    public void setProperties(Properties properties) {
        // 필요한 경우 속성 설정
    }
} 