package com.huashe.park.infrastructure.cfg.mybatis;

import java.util.Collection;
import java.util.Map;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import com.huashe.common.annotation.mybatis.TenantField;

@Intercepts({
    @Signature(type = Executor.class, method = "query", args = {
        MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class
    })
})
@Component
public class TenantIdInterceptor extends BaseInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameterObject = invocation.getArgs()[1];
        Long tenantId = getLoginUser().getUser().getTenantId();
        // 无租户 ID 或无参数对象直接跳过
        if (sqlCommandType != SqlCommandType.SELECT || ObjectUtils.isEmpty(tenantId)
            || ObjectUtils.isEmpty(parameterObject)) {
            return invocation.proceed();
        }

        // 处理集合类型参数（List/数组）
        if (parameterObject instanceof Collection) {
            for (Object item : (Collection<?>) parameterObject) {
                injectTenantId(item, tenantId);
            }
            return invocation.proceed();
        }
        if (parameterObject.getClass().isArray()) {
            for (Object item : (Object[]) parameterObject) {
                injectTenantId(item, tenantId);
            }
            return invocation.proceed();
        }
        injectTenantId(parameterObject, tenantId);

        return invocation.proceed();
    }

    // 公共注入逻辑
    private void injectTenantId(Object target, Long tenantId) {
        if (target == null)
            return;

        // 处理 Map 类型
        if (target instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) target;
            if (!map.containsKey("tenantId")) {
                ((Map<String, Object>) map).put("tenantId", tenantId);
            }
        }
        // 处理实体对象
        else {
            ReflectionUtils.doWithFields(target.getClass(), field -> {
                if (field.isAnnotationPresent(TenantField.class)) {
                    field.setAccessible(true);
                    field.set(target, getLoginUser().getUser().getTenantId());
                    field.setAccessible(false);
                }
            });
        }
    }
}
