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

import java.util.Collection;
import java.util.Date;

import org.apache.ibatis.binding.MapperMethod;
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.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import com.huashe.common.annotation.mybatis.TenantField;
import com.ruoyi.common.core.domain.model.LoginUser;

@Component
@Intercepts({
    @Signature(type = Executor.class, method = "update", args = {
        MappedStatement.class, Object.class
    })
})
public class MybatisInterceptor extends BaseInterceptor implements Interceptor {
    private static final Logger log = LoggerFactory.getLogger(MybatisInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        String sqlId = mappedStatement.getId();
        log.debug("------sqlId------" + sqlId);
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameterObject = invocation.getArgs()[1];
        log.debug("------sqlCommandType------" + sqlCommandType);

        if (parameterObject == null) {
            return invocation.proceed();
        }
        if (parameterObject instanceof MapperMethod.ParamMap) {
            MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) parameterObject;
            for (Object value : paramMap.values()) {
                if (!(value instanceof Collection)) {
                    continue;
                }
                for (Object item : (Collection<?>) value) {
                    injectCreateModifyInfo(item, sqlCommandType);
                }
            }
            return invocation.proceed();
        }
        // 处理集合类型参数（List/数组）
        if (parameterObject instanceof Collection) {
            for (Object item : (Collection<?>) parameterObject) {
                injectCreateModifyInfo(item, sqlCommandType);
            }
            return invocation.proceed();
        }
        if (parameterObject.getClass().isArray()) {
            for (Object item : (Object[]) parameterObject) {
                injectCreateModifyInfo(item, sqlCommandType);
            }
            return invocation.proceed();
        }
        injectCreateModifyInfo(parameterObject, sqlCommandType);
        return invocation.proceed();
    }

    private void injectCreateModifyInfo(Object target, SqlCommandType sqlCommandType) {
        if (target == null) {
            return;
        }
        LoginUser sysUser = getLoginUser();
        if (SqlCommandType.INSERT == sqlCommandType) {
            ReflectionUtils.doWithFields(target.getClass(), field -> {
                field.setAccessible(true);
                if (field.isAnnotationPresent(TenantField.class)) {
                    field.set(target, sysUser.getUser().getTenantId());
                }
                if ("createBy".equals(field.getName())) {
                    Object local_createBy = field.get(target);
                    if (local_createBy == null || local_createBy.equals("")) {
                        if (sysUser != null) {
                            // 登录人账号
                            field.set(target, sysUser.getUser().getNickName());
                        }
                    }
                }
                if ("createName".equals(field.getName())) {
                    Object local_createBy = field.get(target);
                    if (local_createBy == null || local_createBy.equals("")) {
                        if (sysUser != null) {
                            // 登录人账号
                            field.set(target, sysUser.getUser().getNickName());
                        }
                    }
                }
                // 注入创建时间
                if ("createTime".equals(field.getName())) {
                    Object local_createDate = field.get(target);
                    if (local_createDate == null || local_createDate.equals("")) {
                        field.set(target, new Date());
                    }
                }
                field.setAccessible(false);
            });
            return;
        }
        if (SqlCommandType.UPDATE == sqlCommandType) {
            ReflectionUtils.doWithFields(target.getClass(), field -> {
                field.setAccessible(true);
                if ("updateBy".equals(field.getName())) {
                    // 获取登录用户信息
                    if (sysUser != null) {
                        // 登录账号
                        field.set(target, sysUser.getUser().getNickName());
                    }
                }
                if ("updateTime".equals(field.getName())) {
                    field.set(target, new Date());
                }
                field.setAccessible(false);
            });
        }
    }

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

}
