package com.sysu.admin.controller.crop.interceptor;

import com.sysu.admin.controller.crop.executor_table.ExecutorTableService;
import com.sysu.admin.controller.crop.executor_table.QExecutorTable;
import com.sysu.admin.controller.crop.range.AutoTableNameInterceptor;
import com.sysu.admin.controller.crop.range.LandRangeIndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;

/**
 * 用于记录web请求/响应日志
 */
@Component
@Aspect
@Slf4j
public class DynamicTableNamesAspect {

    @Autowired
    @Lazy
    LandRangeIndexService landRangeIndexService;
    @Autowired
    @Lazy
    ExecutorTableService executorTableService;

    public DynamicTableNamesAspect(){
        log.info("DynamicTableNamesAspect started! ");
    }
    /**
     * 切面, 注解名
     */
    @Pointcut("@annotation(DynamicTableNames)")
    private void parameterPointCut() {}

    /**
     * 方法执行前，记录请求
     * @param joinPoint
     */
    @Before("parameterPointCut()")
    public void requestLog(JoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        String value = methodSignature.getMethod().getAnnotation(DynamicTableNames.class).value();
        if(StringUtils.isNotBlank(value)){
            execValue(joinPoint, methodSignature, value);
        }else{
            String executor = methodSignature.getMethod().getAnnotation(DynamicTableNames.class).executor();
            execExecutor(joinPoint, methodSignature, executor);
        }
    }

    private void execExecutor(JoinPoint joinPoint,MethodSignature methodSignature, String executor){
        int i=0;
        for(String paramName : methodSignature.getParameterNames()){
            if(paramName.equals(executor)) {
                Object obj = joinPoint.getArgs()[i];
                String tableNames = executorTableService.getTableNames((Long)obj);
                AutoTableNameInterceptor.myTable.set(tableNames);
                return;
            }
            i++;
        }
    }

    private void execValue(JoinPoint joinPoint,MethodSignature methodSignature, String value){
        int i=0;
        for(String paramName : methodSignature.getParameterNames()){
            if(paramName.equals(value)) {
                Object obj = joinPoint.getArgs()[i];
                String tableNames = null;
                if(obj instanceof Long){
                    tableNames = landRangeIndexService.getTableName((Long)obj);
                }else if(obj instanceof String){
                    tableNames = (String)obj;
                }else if(obj instanceof Double[]){
                    tableNames = landRangeIndexService.getTableName((Double[])obj);
                }else{
                    try {
                        Long id = (Long)obj.getClass().getMethod("getId").invoke(obj);
                        tableNames = landRangeIndexService.getTableName(id);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                AutoTableNameInterceptor.myTable.set(tableNames);
                return;
            }
            i++;
        }
    }

    /**
     * 方法执行后,记录响应
     * @param ret 方法执行结果注入对象
     * @return
     */
    @AfterReturning(returning = "ret",pointcut = "parameterPointCut()")
    public Object responeLog(Object ret){
        AutoTableNameInterceptor.myTable.set(null);
        return ret;
    }
}