package com.util;

import com.business.domain.ImputationData;
import com.business.mapper.ImputationDataMapper;
import com.business.service.ImputationDataService;
import com.sooka.common.utils.DateUtils;
import com.sooka.common.utils.StringUtils;
import com.sooka.system.domain.TUInterfaceinfo;
import com.sooka.system.mapper.TUInterfaceinfoMapper;
import com.sooka.system.service.ITULogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author limeng
 * @date 2022年10月11日 8:50
 */
@Configuration
@EnableScheduling
public class StaticScheduleTask {

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private ITULogService logService;

    @Autowired
    private ImputationDataService imputationDataService;

    @Resource
    private TUInterfaceinfoMapper tUInterfaceinfoMapper;
    @Resource
    private ImputationDataMapper imputationDataMapper;

    /**添加定时任务 每天凌晨1点**/
    /**
     * 刷新归集数据分析 更新当月数据
     */
    @Scheduled(cron = "0 0 1 * * ?")
    private void imputationData() {
        System.out.println("按照年份每年新增一批新数据");
        imputationDataByYear();//按照年份每年新增一批新数据
        System.out.println("按照月份每日更新当月数据");
        imputationDataByMonth();//按照月份每日更新当月数据
    }

    private void imputationDataByMonth() {
        String year = new SimpleDateFormat("yyyy").format(new Date());//String year = "2022";
        String month = new SimpleDateFormat("M").format(new Date());
        TUInterfaceinfo param = new TUInterfaceinfo();
        param.setShareType("share_type_2");//市归集
//        param.setNeedRefresh("1");
        //(164-57) t_guiji_gas_zenner_gas_purchase_center_infor - 归集-市燃气（真兰收费系统）-中心计费购气信息 - 237962 ms
        //(164-70) t_guiji_gas_zenner_meter_reading_infor - 归集-市燃气（真兰收费系统）-抄表信息 - 352968 ms
        List<TUInterfaceinfo> tuInterfaceinfoList = tUInterfaceinfoMapper.selectTUInterfaceinfoList(param);
        for (int i = 0; i < tuInterfaceinfoList.size(); i++) {
            TUInterfaceinfo tuInterfaceinfo = tuInterfaceinfoList.get(i);
            String tableName = tuInterfaceinfo.getTableName();
            if (tableName == null || tableName.equals("") || tableName.equals("t_u_interfaceinfo_emptytable")) {
                System.out.println("(" + tuInterfaceinfoList.size() + "-" + (i + 1) + ") " + tuInterfaceinfo.getTableName() + " - " + tuInterfaceinfo.getInterfaceName() + " - " + 0 + " ms");
                continue;
            }
            ImputationData imputationDataParam = new ImputationData();
            imputationDataParam.setYear(year);
            imputationDataParam.setTableName(tableName);
            boolean isExist = !(imputationDataMapper.selectImputationInterface(imputationDataParam).size() == 0);
            if(!isExist){
                continue;
            }
            Map map = new HashMap();
            map.put("year", year);
            map.put("month", month);
            map.put("tableName", tableName);
            System.out.println(tuInterfaceinfo.getTableName() + " - " + tuInterfaceinfo.getInterfaceName() + " - " + "updating database... id = " + tuInterfaceinfo.getId());
            Map column = new HashMap();
            column.put("tableSchema", tableName.contains("\\.") ? tableName.split("\\.")[0] : "thsjzt");//thgjj / thsjzt
            column.put("tableName", tableName.contains("\\.") ? tableName.split("\\.")[1] : tableName);//thgjj.tgjj_gtjkrxx / t_guiji_gas_zenner_meter_reading_infor
            column.put("columnName", "create_time");//create_time / LAST_UPDATE_TIME
//            System.out.println(column.get("tableSchema"));
//            System.out.println(column.get("tableName"));
//            System.out.println(column.get("columnName"));
            List<Object> objectList = tUInterfaceinfoMapper.checkColumnExists(column);
            System.out.println(objectList.size() + "=object");
            Date dateBegin = new Date();
            ImputationData imputationData;
            if(objectList.size() != 0){
                imputationData = tUInterfaceinfoMapper.imputationDataByMonth(map);
            }else {
                imputationData = tUInterfaceinfoMapper.imputationDataByMonthLastUpdateTime(map);
            }
            Long interval = new Date().getTime() - dateBegin.getTime();//接口查询总数所用时间
            ImputationData imputationDataInsert = new ImputationData();
            imputationDataInsert.setYear(year);
            imputationDataInsert.setMonth(month);
            imputationDataInsert.setTableName(tableName);
//            imputationDataInsert.setInterfaceName(tuInterfaceinfo.getInterfaceName());//接口名称可能会变
            imputationDataInsert.setCount(imputationData.getCount());
            imputationDataMapper.updateImputationInterfaceByYearMonthTableName(imputationDataInsert);
            System.out.println("(" + tuInterfaceinfoList.size() + "-" + (i + 1) + ") " + tuInterfaceinfo.getTableName() + " - " + tuInterfaceinfo.getInterfaceName() + " - " + interval + " ms");
        }
    }

    private void imputationDataByYear() {
        String year = new SimpleDateFormat("yyyy").format(new Date());//String year = "2022";
        TUInterfaceinfo param = new TUInterfaceinfo();
        param.setShareType("share_type_2");//市归集
//        param.setNeedRefresh("1");
        //(164-57) t_guiji_gas_zenner_gas_purchase_center_infor - 归集-市燃气（真兰收费系统）-中心计费购气信息 - 237962 ms
        //(164-70) t_guiji_gas_zenner_meter_reading_infor - 归集-市燃气（真兰收费系统）-抄表信息 - 352968 ms
        List<TUInterfaceinfo> tuInterfaceinfoList = tUInterfaceinfoMapper.selectTUInterfaceinfoList(param);
        for (int i = 0; i < tuInterfaceinfoList.size(); i++) {
            TUInterfaceinfo tuInterfaceinfo = tuInterfaceinfoList.get(i);
            String tableName = tuInterfaceinfo.getTableName();
            if (tableName == null || tableName.equals("") || tableName.equals("t_u_interfaceinfo_emptytable")) {
                System.out.println("(" + tuInterfaceinfoList.size() + "-" + (i + 1) + ") " + tuInterfaceinfo.getTableName() + " - " + tuInterfaceinfo.getInterfaceName() + " - " + 0 + " ms");
                continue;
            }
            ImputationData imputationDataParam = new ImputationData();
            imputationDataParam.setYear(year);
            imputationDataParam.setTableName(tableName);
            boolean isExist = !(imputationDataMapper.selectImputationInterface(imputationDataParam).size() == 0);
            if(isExist){
                continue;
            }
            Map map = new HashMap();
            map.put("year", year);
            map.put("tableName", tableName);
            System.out.println(tuInterfaceinfo.getTableName() + " - " + tuInterfaceinfo.getInterfaceName() + " - " + "updating database... id = " + tuInterfaceinfo.getId());
            Map column = new HashMap();
            column.put("tableSchema", tableName.contains("\\.") ? tableName.split("\\.")[0] : "thsjzt");//thgjj / thsjzt
            column.put("tableName", tableName.contains("\\.") ? tableName.split("\\.")[1] : tableName);//thgjj.tgjj_gtjkrxx / t_guiji_gas_zenner_meter_reading_infor
            column.put("columnName", "create_time");//create_time / LAST_UPDATE_TIME
            System.out.println(column.get("tableSchema"));
            System.out.println(column.get("tableName"));
            System.out.println(column.get("columnName"));
            List<Object> objectList = tUInterfaceinfoMapper.checkColumnExists(column);
            System.out.println(objectList.size() + "=object");
            Date dateBegin = new Date();
            ImputationData imputationData;
            if(objectList.size() != 0){
                imputationData = tUInterfaceinfoMapper.imputationData(map);
            }else {
                imputationData = tUInterfaceinfoMapper.imputationDataLastUpdateTime(map);
            }
            Long interval = new Date().getTime() - dateBegin.getTime();//接口查询总数所用时间
            ImputationData imputationDataInsert = new ImputationData();
            imputationDataInsert.setYear(year);
            imputationDataInsert.setTableName(tableName);
            imputationDataInsert.setInterfaceName(tuInterfaceinfo.getInterfaceName());
            imputationDataInsert.setJan(imputationData.getJan());
            imputationDataInsert.setFeb(imputationData.getFeb());
            imputationDataInsert.setMar(imputationData.getMar());
            imputationDataInsert.setApr(imputationData.getApr());
            imputationDataInsert.setMay(imputationData.getMay());
            imputationDataInsert.setJun(imputationData.getJun());
            imputationDataInsert.setJul(imputationData.getJul());
            imputationDataInsert.setAug(imputationData.getAug());
            imputationDataInsert.setSep(imputationData.getSep());
            imputationDataInsert.setOct(imputationData.getOct());
            imputationDataInsert.setNov(imputationData.getNov());
            imputationDataInsert.setDecb(imputationData.getDecb());
            imputationDataMapper.insertImputationInterface(imputationDataInsert);
            System.out.println("(" + tuInterfaceinfoList.size() + "-" + (i + 1) + ") " + tuInterfaceinfo.getTableName() + " - " + tuInterfaceinfo.getInterfaceName() + " - " + interval + " ms");
        }
    }

    /**添加定时任务 每天凌晨1点**/
    //@Scheduled(cron = "0 0 1 * * ?")
    private void configureTasks() {
        for(int i=0;i<getYears().length;i++){
            Map map = logService.selectImputationLog(getYears()[i]);
            try {
                ImputationData imputationData = new ImputationData();
                imputationData.setYear(getYears()[i]);
                ImputationData imd = imputationDataService.selectImputationData(imputationData);
                ImputationData id = (ImputationData) mapToBean(map,new ImputationData().getClass());
                if(imd == null){
                    imputationDataService.insertImputationData(id);
                }
                imputationDataService.updateImputationData(id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**获取当前年和前四年的年份**/
    private String[] getYears() {
        String[] arr = new String[5];
        for(int i=0;i<arr.length;i++){
            arr[i] = getYears(i-4);
        }
        return arr;
    }

    /**
     * @Description 获取年份
     * @param num 负数为之前年,0为当前年,正数为之后年
     * @Throws
     * @Return java.lang.String
     * @Date 2022-10-12 10:28:15
     * @Author
     **/
    public static String getYears(int num) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.YEAR, num);
        Date y = c.getTime();
        return format.format(y);
    }

    /**比较两个日期大小**/
    private boolean daysBefore(String time) {
        Calendar calendar = null;
        try {
            calendar = getCalendar(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar now = Calendar.getInstance();
        return calendar.before(now);
    }

    /**将String时间转换为Calendar**/
    private static Calendar getCalendar(String time) throws ParseException {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(simpleDateFormat.parse(time));
        return calendar;
    }

    /**
     * 利用反射将map集合封装成bean对象
     *
     * @param map
     * @param clazz
     * @return
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<?> clazz) throws Exception {
        Object obj = clazz.newInstance();
        if (map != null && !map.isEmpty() && map.size() > 0) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                // 属性名
                String propertyName = entry.getKey();
                // 属性值
                Object value = entry.getValue();
                String setMethodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                //获取和map的key匹配的属性名称
                Field field = getClassField(clazz, propertyName);
                if (field == null){
                    continue;
                }
                Class<?> fieldTypeClass = field.getType();
                value = convertValType(value, fieldTypeClass);
                try {
                    clazz.getMethod(setMethodName, field.getType()).invoke(obj, value);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        }
        return (T) obj;
    }

    /**
     * 根据给定对象类匹配对象中的特定字段
     * @param clazz
     * @param fieldName
     * @return
     */
    private static Field getClassField(Class<?> clazz, String fieldName) {
        if (Object.class.getName().equals(clazz.getName())) {
            return null;
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }
        //如果该类还有父类，将父类对象中的字段也取出
        Class<?> superClass = clazz.getSuperclass();
        //递归获取
        if (superClass != null) {
            return getClassField(superClass, fieldName);
        }
        return null;
    }

    /**
     * 将map的value值转为实体类中字段类型匹配的方法
     * @param value
     * @param fieldTypeClass
     * @return
     */
    private static Object convertValType(Object value, Class<?> fieldTypeClass) {
        Object retVal = null;
        if (Long.class.getName().equals(fieldTypeClass.getName())
                || long.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Long.parseLong(value.toString());
        } else if (Integer.class.getName().equals(fieldTypeClass.getName())
                || int.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Integer.parseInt(value.toString());
        } else if (Float.class.getName().equals(fieldTypeClass.getName())
                || float.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Float.parseFloat(value.toString());
        } else if (Double.class.getName().equals(fieldTypeClass.getName())
                || double.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Double.parseDouble(value.toString());;
        } else {
            retVal = value.toString();
        }
        return retVal;
    }




}
