package com.ruoyi.framework.interceptor;

import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.framework.web.domain.BaseEntity;
import lombok.extern.slf4j.Slf4j;
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.Signature;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class MybatisAutoFillInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        SqlCommandType commandType = mappedStatement.getSqlCommandType();
        Object data = invocation.getArgs()[1];
        List<Object> list = new ArrayList<>();
        if (data instanceof BaseEntity){
            list.add(data);
        } else if (data instanceof MapperMethod.ParamMap){
            MapperMethod.ParamMap map = (MapperMethod.ParamMap) data;
            if (map.containsKey("list")){
                List dataList = (ArrayList) map.get("list");
                dataList.forEach(row -> {
                    if (row instanceof BaseEntity){
                        list.add(row);
                    }
                });
            }
        }

        Long currentUser;
        try {
            currentUser = SecurityUtils.getUserId();
        } catch (Exception e){
            // 定时任务会获取不到
            currentUser = 1L;
        }

        String finalCurrentUser = currentUser.toString();
        Date now = new Date();
        for (Object row: list) {
            if (commandType == SqlCommandType.INSERT) {
                if (ReflectUtils.getAccessibleField(row, "delFlag") != null) {
                    ReflectUtils.setFieldValue(row, "delFlag", "0");
                }
                ReflectUtils.setFieldValue(row, "createBy", finalCurrentUser);
                ReflectUtils.setFieldValue(row, "createTime", now);
                ReflectUtils.setFieldValue(row, "updateBy", finalCurrentUser);
                ReflectUtils.setFieldValue(row, "updateTime", now);
            }
            if (commandType == SqlCommandType.UPDATE) {
                ReflectUtils.setFieldValue(row, "updateBy", finalCurrentUser);
                ReflectUtils.setFieldValue(row, "updateTime", now);
            }
        }

        return invocation.proceed();
    }

}

