package com.sckw.core.aspect;

import com.sckw.core.model.constant.Global;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.web.context.LoginUserHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

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

/**
 * DAO切面，插入创建人，创建时间，修改人，修改时间
 *
 * @author zk
 * @date Oct 29, 2018
 */
@Aspect
@Component
@Configuration
public class DaoAspect {
    private static final String ID = "id";
    private static final String STATUS = "status";
    private static final String CREATE_BY = "createBy";
    private static final String CREATE_BY_NAME = "createByName";
    private static final String CREATE_TIME = "createTime";
    private static final String UPDATE_BY = "updateBy";
    private static final String UPDATE_BY_NAME = "updateByName";
    private static final String UPDATE_TIME = "updateTime";
    private static final String DEL_FLAG = "delFlag";

    @Pointcut("execution(* com.sckw.*.dao.*.update*(..))")
    public void daoUpdate() {
    }

    @Pointcut("execution(* com.sckw.*.dao.*.insert*(..))")
    public void daoCreate() {
    }

    @Around("daoUpdate()")
    public Object doAroundUpdate(ProceedingJoinPoint point) throws Throwable {
        /*ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return point.proceed();
        }
        HttpServletRequest request = attributes.getRequest();*/
        Object[] objects = point.getArgs();
        if (objects != null) {
            for (Object arg : objects) {
                List<Object> objs = CollectionUtils.objectCastList(arg, Object.class);
                if (CollectionUtils.isEmpty(objs)) {
                    objs.add(arg);
                }
                Long userId = LoginUserHolder.getUserId();
                objs.forEach(obj -> {
                    if (isProperty(obj, UPDATE_BY) && !userId.equals(1L)) {
                        BeanUtils.setProperty(obj, UPDATE_BY, userId);
                    }
                    if (isProperty(obj, UPDATE_TIME)) {
                        BeanUtils.setProperty(obj, UPDATE_TIME, new Date());
                    }
                });
            }
        }
        return point.proceed();
    }

    @Around("daoCreate()")
    public Object doAroundCreate(ProceedingJoinPoint point) throws Throwable {
        /*ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return point.proceed();
        }
        HttpServletRequest request = attributes.getRequest();*/
        Object[] objects = point.getArgs();
        if (objects != null) {
            for (Object arg : objects) {
                List<Object> objs = CollectionUtils.objectCastList(arg, Object.class);
                if (CollectionUtils.isEmpty(objs)) {
                    objs.add(arg);
                }
                Date date = new Date();
                objs.forEach(obj -> {
                    Long userId = LoginUserHolder.getUserId();
                    if (isProperty(obj, CREATE_BY) && Objects.isNull(BeanUtils.getProperty(obj, CREATE_BY))) {
                        BeanUtils.setProperty(obj, CREATE_BY, userId);
                    }
                    if (isProperty(obj, UPDATE_BY) && Objects.isNull(BeanUtils.getProperty(obj, UPDATE_BY))) {
                        BeanUtils.setProperty(obj, UPDATE_BY, userId);
                    }

//                if (userName != null){
//                    if (isProperty(arg, CREATE_BY_NAME) && StringUtils.isBlank(BeanUtils.getProperty(arg, CREATE_BY_NAME))) {
//                        BeanUtils.setProperty(arg, CREATE_BY_NAME, userName);
//                    }
//                    if (isProperty(arg, UPDATE_BY_NAME) && StringUtils.isBlank(BeanUtils.getProperty(arg, UPDATE_BY_NAME))) {
//                        BeanUtils.setProperty(arg, UPDATE_BY_NAME, userName);
//                    }
//                }

                    if (isProperty(obj, CREATE_TIME) && Objects.isNull(BeanUtils.getProperty(obj, CREATE_TIME))) {
                        BeanUtils.setProperty(obj, CREATE_TIME, date);
                    }

                    if (isProperty(obj, UPDATE_TIME) && Objects.isNull(BeanUtils.getProperty(obj, UPDATE_TIME))) {
                        BeanUtils.setProperty(obj, UPDATE_TIME, date);
                    }

                    if (isProperty(obj, ID) && Objects.isNull(BeanUtils.getProperty(obj, ID))) {
                        BeanUtils.setProperty(obj, ID, new IdWorker(1).nextId());
                    }

                    if (isProperty(obj, STATUS) && Objects.isNull(BeanUtils.getProperty(obj, STATUS))) {
                        BeanUtils.setProperty(obj, STATUS, Global.NO);
                    }

                    if (isProperty(obj, DEL_FLAG) && Objects.isNull((BeanUtils.getProperty(obj, DEL_FLAG)))) {
                        BeanUtils.setProperty(obj, DEL_FLAG, Global.NO);
                    }
                });
            }
        }
        return point.proceed();
    }

    public static boolean isProperty(Object bean, String field) {
        return BeanUtils.isProperty(bean, field);
    }
}
