package com.bcxin.ins.service.order.impl;

import com.alibaba.fastjson.JSONObject;
import com.bcxin.ins.core.entity.ME;
import com.bcxin.ins.core.entity.SysMenu;
import com.bcxin.ins.dao.order.ComTaskResidualAPIDao;
import com.bcxin.ins.service.order.ComTaskResidualAPIService;
import com.bcxin.ins.entity.common.ComTaskResidual;
import com.bcxin.ins.spring.executor.MyAsyncExecutor;
import com.bcxin.ins.spring.util.SpringContextHolder;
import com.bcxin.ins.vo.shop.ImportInsuranceOrderRequest;
import com.bcxin.mybatisplus.mapper.EntityWrapper;
import com.bcxin.mybatisplus.service.impl.ServiceImpl;
import com.bcxin.mybatisplus.toolkit.StringUtils;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;


@Service
@Transactional
public class ComTaskResidualAPIServiceImpl extends ServiceImpl<ComTaskResidualAPIDao, ComTaskResidual> implements ComTaskResidualAPIService {

    @Autowired
    private ComTaskResidualAPIDao dao;

    @Autowired
    private MyAsyncExecutor myAsyncExecutor;

    private Logger log =  LoggerFactory.getLogger(ComTaskResidualAPIServiceImpl.class);

    /**
     * <b> 查询所有记录，遍历反射获取方法重新加载，如果接口返回true删除当前记录 </b>
     * 该方法当期用于定时器定时处理，处理时采用异步，另开线程执行该业务
     * @param is_nightly_run 是否夜间执行，是：1，不是：""
     * @author ZXF
     * @create 2018/04/03 0003 15:54
     * @version
     * @注意事项 </b>
     */
    @Override
    public void disposeComTaskResidualList(String is_nightly_run){
        Map<String, Object> columnMap = Maps.newHashMap();
        if(StringUtils.isNotEmpty(is_nightly_run)){
            columnMap.put("is_nightly_run",is_nightly_run);
        }
        List<ComTaskResidual> ctrList = dao.selectByMap(columnMap);
        for (ComTaskResidual ctr : ctrList){
            try {
                Thread.sleep(300);
                myAsyncExecutor.execute(()->{
                    applyReturnBooleanOfClassReflect(ctr);
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * <b> 类反射 </b>
     *  只适用于方法返回布尔值的ComTaskResidual用
     *  如果这次跑成功就把该数据从数据库中删除
     *  如果传的是对象则必须只能有一个参数
     * @author ZXF
     * @create 2018/03/19 0019 14:06
     * @version
     * @注意事项 </b>
     */
    @Override
    public void applyReturnBooleanOfClassReflect(ComTaskResidual ctr){
        ClassLoader cls = Thread.currentThread().getContextClassLoader();
        String errEsg = "";
        try {
            Class c =  cls.loadClass(ctr.getClass_name());
            String[] tArr = ctr.getParam_type_arr().split(",");
            String[] vArr = ctr.getParam_value_arr().split(",", -1);
            Class[] csArr = new Class[ctr.getParam_num()];
            Object[] otArr = new Object[ctr.getParam_num()];
            for(int i = 0; i<ctr.getParam_num();i++){
                String tp = tArr[i];
                if("String".equals(tp)){
                    csArr[i] = String.class;
                    otArr[i] = String.valueOf(vArr[i]);
                }else if("int".equals(tp)){
                    csArr[i] = int.class;
                    otArr[i] = Integer.parseInt(vArr[i]);
                }else if("BigDecimal".equals(tp)){
                    csArr[i] = BigDecimal.class;
                    otArr[i] = new BigDecimal(vArr[i]);
                }else if("Long".equals(tp)){
                    csArr[i] = Long.class;
                    otArr[i] = Long.parseLong(vArr[i]);
                }else if("com.bcxin.ins.vo.shop.ImportInsuranceOrderRequest".equals(tp)){
                    csArr[i] = ImportInsuranceOrderRequest.class;
                    otArr[i] = JSONObject.parseObject(ctr.getParam_value_arr(),Class.forName(ctr.getParam_type_arr()));
                }else{
                    csArr[i] = Object.class;
                    otArr[i] = JSONObject.parseObject(ctr.getParam_value_arr(),Class.forName(ctr.getParam_type_arr()));
                }
            }
            Object o =  SpringContextHolder.getBean(c);
            Method method = o.getClass().getDeclaredMethod(ctr.getMethod_name(),csArr);
            method.setAccessible(true);
            Object r = method.invoke(o, otArr);
            boolean ret = false;
            if (r != null&&r.getClass().equals(Boolean.class)){
                ret = (boolean)r;
            }else if (r != null&&r.getClass().equals(String.class)){
                ret = true;
            }
            if(ret){
                dao.deleteById(ctr.getCom_task_residual_id());
            }else{
                errEsg = "Apply Method Fail!!--------------------------";
            }
        } catch (ClassNotFoundException e) {
            errEsg = e.getMessage();
        } catch (IllegalAccessException e) {
            errEsg = e.getMessage();
        } catch (NoSuchMethodException e) {
            errEsg = e.getMessage();
        } catch (SecurityException e) {
            errEsg = e.getMessage();
        } catch (IllegalArgumentException e) {
            errEsg = e.getMessage();
        } catch (InvocationTargetException e) {
            errEsg = e.getMessage();
        }
        if(StringUtils.isNotEmpty(errEsg)){
            log.info("----------ComTaskResidual未成功任务反射执行（"+ctr.getAnnotation()+"）,ExceptionMessage："+errEsg);
        }
    }

    /**
     * <b> 创建一条接口为成功数据，等待定时器跑 </b>
     * @param method_name 方法名
     * @param annotation 注释
     * @param class_name 所在类的全路径
     * @param param_num 参数个数
     * @param param_type_arr 参数类型（多个用,隔开）
     * @param param_value_arr 参数值（多个用,隔开）
     * @author ZXF
     * @create 2018/04/03 0003 14:49
     * @version
     * @注意事项 </b>
     */
    @Override
    public void saveComTaskResidual(String method_name, String annotation, String class_name, int param_num, String param_type_arr, String param_value_arr) {
        List<ComTaskResidual> list = dao.selectList(new EntityWrapper<ComTaskResidual>().addFilter("method_name = {0} and param_value_arr = {1}",method_name,param_value_arr));
        if(list.size()>0){
            System.out.println("=======> 打回打回");
            return;
        }
        ComTaskResidual ctr = new ComTaskResidual(method_name
                ,annotation
                ,class_name
                ,param_num
                ,param_type_arr
                ,param_value_arr
                ,"0"
        );
        myAsyncExecutor.execute(()->{
            dao.insert(ctr);
        });
    }

    /**
     * <b> 创建一条接口为成功数据，等待定时器跑(专用于晚间执行的定时任务) </b>
     * @param method_name 方法名
     * @param annotation 注释
     * @param class_name 所在类的全路径
     * @param param_num 参数个数
     * @param param_type_arr 参数类型（多个用,隔开）
     * @param param_value_arr 参数值（多个用,隔开）
     * @param param_value_arr 参数值（多个用,隔开）
     * @author ZXF
     * @create 2018/04/03 0003 14:49
     * @version
     * @注意事项 </b>
     */
    @Override
    public void saveComTaskResidual2(String method_name, String annotation, String class_name, int param_num, String param_type_arr, String param_value_arr) {
        ComTaskResidual ctr = new ComTaskResidual(method_name
                ,annotation
                ,class_name
                ,param_num
                ,param_type_arr
                ,param_value_arr
                ,"1"
        );
        myAsyncExecutor.execute(()->{
            dao.insert(ctr);
        });
    }

    public static void main(String[] args) {
        ComTaskResidualAPIServiceImpl c = new ComTaskResidualAPIServiceImpl();
        ComTaskResidual ctr = c.selectById(1026392461119287297L);
        c.applyReturnBooleanOfClassReflect(ctr);
        /*ComTaskResidual ctr = new ComTaskResidual("testReflect"
                ,"测试方法"
                ,"com.bcxin.ins.service.order.PolicyService"
                ,3
                ,"String"
                ,"呵呵"
        );*/
//        applyReturnBooleanOfClassReflect(ctr);
    }
}
