package com.tofly.common.oauth.handler;

import com.tofly.base.api.feign.FlowableService;
import com.tofly.common.core.constant.SecurityConstants;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.core.util.Date8Util;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.oauth.util.ToflyDataTypeConstant;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 〈一句话功能简述〉<br>
 * 〈定时自动同步流程数据到业务数据〉开启异步多线程方式
 *
 * @author wj
 * @create 2020/2/5 9:20
 * @since 1.0.0
 */
//@Component
@EnableScheduling   // 1.开启定时任务
@EnableAsync        // 2.开启多线程
@Slf4j
public class AutoUploadForm{

    //@Autowired
    private FlowableService flowableService;

    private String appName;

    public void setAppName(String appName){
        this.appName=appName;
    }

    public void setFlowableService(FlowableService flowableService){
        this.flowableService=flowableService;
    }

    @Autowired
    private ToflyDataTypeConstant toflyDataTypeConstant;


    @Autowired
    private JdbcTemplate jdbcTemplate;

    private String SELECTUPLOADFORM_SQL="select * from table where proc_id=?";

    private String NOWTIME_SQL="nowtime";

    private  String  INSERTFORM_SQL="INSERT INTO table(proc_id,create_time,cols) values(?,"+NOWTIME_SQL+",thisvalues)";
    private String UPLOADFORM_SQL="update table set cols2 where proc_id=?";

    @Async
    @Scheduled(cron = "${tofly.flupload.time}")  //间隔5秒
    // @Scheduled(fixedDelay = 5000)  //间隔5秒
    @SneakyThrows
    public void uploadForm(){

        System.out.println(Date8Util.getCurrentDate().toString()+ Thread.currentThread()+"-----------------来了：appform:"+appName+",,,appName:"+appName);

        if(StringUtil.isEmpty(appName)){
            log.error("未获取到appName，不执行同步操作");
            return;
        }
        ResultRespone resultRespone;
        try {
            resultRespone=flowableService.uploadForm(appName, SecurityConstants.FROM_IN);
        }catch (Exception e){
            log.error("表单同步业务远程调用失败："+e.getMessage());
            return;
        }
        INSERTFORM_SQL=INSERTFORM_SQL.replace(NOWTIME_SQL,toflyDataTypeConstant.getNowTimeSql());

        if(resultRespone.getCode()!=-1){
            List<Map> list=(List<Map>)resultRespone.getResult();
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            if(list!=null && list.size()>0){
                list.forEach(m->{
                    final Map<String, Object> mycollect = ((List<Map>) m.get("data")).stream()
                            .filter(k->StringUtil.isNotEmpty((String)k.get("text")))
                            .collect(Collectors.toMap(k ->(String)k.get("name"), v ->
                            {
                                String type=(String)v.get("vtype");
                                Object reO=null;
                                switch (type){
                                    case "string":
                                        reO=(String)v.get("text");
                                        break;
                                    case "int":
                                        reO=(Integer)v.get("text");
                                        break;
                                    case "date":
                                        String value=(String)v.get("text");
                                        java.util.Date d = null;
                                        try {
                                            d=sdf.parse(value);
                                        }catch (ParseException s){
                                            log.error("格式化日期出错：{},{}",value,s);
                                        }
                                        reO=new java.sql.Date(d.getTime());
                                        break;
                                    case "time":
                                        String vt=(String)v.get("text");
                                        java.util.Date d2 = null;
                                        try {
                                            d2 = sdf2.parse(vt);
                                        }catch (ParseException s){
                                            log.error("格式化日期出错：{},{}",vt,s);
                                        }
                                        reO=new java.sql.Time(d2.getTime());
                                        break;
                                    default:
                                        reO=v.get("text");
                                }
                                return reO;
                            }
                            ));
                    String seSql= SELECTUPLOADFORM_SQL.replace("table",(String) m.get("FROM_APPTABLE"));

                    List maps = jdbcTemplate.queryForList(seSql, (String) m.get("PROC_ID"));
                    String exeSql;
                    if(maps==null || maps.size()==0){
                        StringBuilder sb=new StringBuilder(),sbValue=new StringBuilder();
                        mycollect.forEach((k,v)->{sb.append(k).append(",");sbValue.append("?").append(",");});
                        String relace=sb.substring(0,sb.lastIndexOf(","));
                        exeSql=INSERTFORM_SQL.replace("table",(String) m.get("FROM_APPTABLE"));
                        exeSql=exeSql.replace("cols",relace);
                        exeSql=exeSql.replace("thisvalues",sbValue.substring(0,sbValue.lastIndexOf(",")));
                        jdbcTemplate.update(exeSql, new PreparedStatementSetter() {
                            @Override
                            public void setValues(PreparedStatement preparedStatement) throws SQLException {
                                preparedStatement.setString(1,(String) m.get("PROC_ID"));
                                int i=2;
                                for(Map.Entry<String, Object> it : mycollect.entrySet()){
                                    try {
                                        preparedStatement.setObject(i,it.getValue());
                                    }catch (SQLException s){
                                        log.error("传参错误");
                                    }
                                    i++;
                                }

//                                mycollect.forEach((k,v)->{
//                                    try {
//                                        preparedStatement.setString(i,k);
//                                        preparedStatement.setObject(size+1+i,v);
//                                    }catch (SQLException s){
//                                        log.error("传参错误");
//                                    }
//                                    i++;
//                                });
                            }
                        });
                    }else {
                        StringBuilder sb=new StringBuilder();
                        mycollect.forEach((k,v)->{sb.append(k).append("=?").append(",");});
                        String relace=sb.substring(0,sb.lastIndexOf(","));
                        exeSql=UPLOADFORM_SQL.replace("table",(String) m.get("FROM_APPTABLE"));
                        exeSql=exeSql.replace("cols2",relace);
                        jdbcTemplate.update(exeSql, new PreparedStatementSetter() {
                            @Override
                            public void setValues(PreparedStatement preparedStatement) throws SQLException {
                                int i=1;
                                int size=mycollect.size();
                                for(Map.Entry<String, Object> it : mycollect.entrySet()){
                                    try {
                                        preparedStatement.setObject(i,it.getValue());
                                    }catch (SQLException s){
                                        log.error("传参错误");
                                    }
                                    i++;
                                }
                                preparedStatement.setString(i,(String) m.get("PROC_ID"));
                            }
                        });
                    }
                });
            }
        }else {
            log.error("未获取到数据:",resultRespone.getMessage());
        }
    }
}
