
package com.lideeyunji.core.framework.config.aspect.enhancereport;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lideeyunji.core.framework.config.aspect.enhance.LideeYunJiBaseEnhance;
import com.lideeyunji.core.framework.config.aspect.enhance.model.EnhanceResult;
import com.lideeyunji.core.framework.config.aspect.enhance.model.JavaEnhanceEnum;
import com.lideeyunji.core.framework.config.aspect.enhancereport.annotation.LideeyunJiReportEnhance;
import com.lideeyunji.core.framework.config.aspect.enhancereport.enums.RefreshPluginEnums;
import com.lideeyunji.core.framework.config.aspect.enhancereport.model.BuildEnhanceReportContext;
import com.lideeyunji.core.framework.config.aspect.enhancereport.model.EnhanceReportContext;
import com.lideeyunji.core.framework.config.aspect.enhancereport.model.EnhanceReportParam;
import com.lideeyunji.core.framework.config.aspect.enhancereport.plugin.ReportAfterAdvicePlugin;
import com.lideeyunji.core.framework.config.aspect.enhancereport.plugin.ReportBaseAdvicePlugin;
import com.lideeyunji.core.framework.config.aspect.enhancereport.plugin.ReportPluginManager;
import com.lideeyunji.core.framework.entity.ReportEntity;
import com.lideeyunji.core.framework.service.IReportService;
import com.lideeyunji.core.framework.utils.Func;
import com.lideeyunji.tool.framework.exception.lideeYunJiException;
import com.lideeyunji.tool.framework.yunji.model.ResultDataModel;
import com.lideeyunji.tool.framework.yunji.tool.spring.SpringUtils;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 报表统计
 */
@Aspect
@Component
@Slf4j
public class LideeYunJiReportEnhance extends LideeYunJiBaseEnhance {


    //需要处理的增强  key=报表code  value=增强
    private static Map<String, String> pluginNames = new HashMap<>();

    @Lazy
    @Autowired
    private IReportService reportService;

    //初始化插件
    @PostConstruct
    public void initReportEnhanceMaps() {
        //获取所有增强
        LambdaQueryWrapper<ReportEntity> wrapper=new LambdaQueryWrapper<>();
        wrapper.isNotNull(ReportEntity::getJavaConfig);
        List<ReportEntity> reportEntityList = reportService.list(wrapper);
        if(Func.isEmpty(reportEntityList)){
            return;
        }
        reportEntityList.forEach(reportEntity->{
            LideeYunJiReportEnhance.refreshPlugin(RefreshPluginEnums.ADD,reportEntity.getReportCode(),reportEntity.getJavaConfig());
        });
    }


    @AfterReturning(pointcut = "@annotation(lideeyunJiReportEnhance)", returning = "returnVal")
    public Object afterReturning(JoinPoint joinPoint, Object returnVal, LideeyunJiReportEnhance lideeyunJiReportEnhance) throws Throwable {

        //获取参数
        BuildEnhanceReportContext buildEnhanceContext = this.getContextAndPlugins(joinPoint);
        if (FuncBase.isEmpty(buildEnhanceContext)) {//没有增强
            return returnVal;
        }

        //增强列表
        String javaClass = buildEnhanceContext.getJavaClass();
        if (Func.isEmpty(javaClass)) {//无增强
            return returnVal;
        }
        //有增强，但是增强不是报表增强，直接返回原值
        ReportBaseAdvicePlugin plugin = ReportPluginManager.getPlugin(javaClass);
        if (!(plugin instanceof ReportAfterAdvicePlugin)) {
            return returnVal;
        }

        EnhanceReportContext context = buildEnhanceContext.getContext();


        //把原来返回值封装到上下文context
        ResultDataModel resultDataModel = (ResultDataModel) returnVal;
        List<Map<String, Object>> records = resultDataModel.getRecords();
        if(Func.isEmpty(records)){
            records=new ArrayList<>();
        }

        EnhanceResult enhanceResult = new EnhanceResult();
        enhanceResult.setRecords(records);
        enhanceResult.setTotal((long)records.size());
        context.getParam().setList(records);
        context.setResult(enhanceResult);

        //执行增强
        ReportPluginManager.executePlugin(javaClass, context);

        //返回结果
        ResultDataModel returnValData = (ResultDataModel) returnVal;
        resultDataModel = super.getResult(context);
        //重新赋值
        returnValData.setRecords(resultDataModel.getRecords());
        returnValData.setTotal(resultDataModel.getTotal());
        return returnValData;

    }

    private BuildEnhanceReportContext getContextAndPlugins(JoinPoint joinPoint) {
        Map<String, Object> paramMap = super.getJoinPointParam(joinPoint);

        //判断该表单，当前的功能是否有增强
        String reportCode = Func.getMap2Str(paramMap, "reportCode");
        String javaClass = pluginNames.getOrDefault(reportCode, null);
        if (Func.isEmpty(javaClass)) {//不存在增强
            return null;
        }

        EnhanceReportParam param = super.getReportEnhanceParam(reportCode, paramMap);
        //把参数放入到上下文
        EnhanceReportContext context = new EnhanceReportContext();
        context.setParam(param);

        BuildEnhanceReportContext buildEnhanceContext = new BuildEnhanceReportContext(context, javaClass);
        return buildEnhanceContext;
    }

    //刷新插件
    public  static void refreshPlugin(RefreshPluginEnums refreshPluginEnums, String reportCode, String javaClass){
        try {
            if(Func.isEmpty(javaClass)){
                return;
            }

            if(Func.equals(RefreshPluginEnums.ADD,refreshPluginEnums) ||Func.equals(RefreshPluginEnums.UPDATE,refreshPluginEnums)){
                JavaEnhanceEnum javaEnhanceEnum=javaClass.indexOf(".")>0?JavaEnhanceEnum.CLASS:JavaEnhanceEnum.SPRING;
                if(Func.equals(javaEnhanceEnum,JavaEnhanceEnum.SPRING)){
                    Object bean = SpringUtils.getBean(javaClass);
                    if (Func.isNotEmpty(bean) && bean instanceof ReportBaseAdvicePlugin) {
                        ReportPluginManager.addPlugin(javaClass, (ReportBaseAdvicePlugin) bean);
                        pluginNames.put(reportCode,javaClass);
                    }
                }else{
                    Class<?> enhanceClass = Class.forName(javaClass);
                    ReportBaseAdvicePlugin plugin = (ReportBaseAdvicePlugin) enhanceClass.newInstance();
                    ReportPluginManager.addPlugin(javaClass, plugin);
                    pluginNames.put(reportCode,javaClass);
                }
            }else if(Func.equals(RefreshPluginEnums.DEL,refreshPluginEnums)){
                pluginNames.remove(reportCode,javaClass);
                if (!new HashSet<>(pluginNames.values()).contains(javaClass)) {
                    ReportPluginManager.removePlugin(javaClass);
                }
            }

        } catch (Exception e) {
            //e.printStackTrace();
            throw new lideeYunJiException("增强["+javaClass+"]插件加载失败");
        }
    }


}
