package cn.gov.customs.data.timer;

import cn.gov.customs.data.entity.wxjy.common.PubCustomsMapping;
import cn.gov.customs.data.repository.iedg.IedgRepository;
import cn.gov.customs.data.repository.wxjy.WxjyRepository;
import cn.gov.customs.data.repository.wxjy.common.PubCustomsMappingRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 综合处危险品数据
 *
 * @author wq
 */
@Component
@PropertySource("classpath:data-acquisition.properties")
public class ZhDataRunTask {
    Logger logger = LoggerFactory.getLogger(ZhDataRunTask.class);

    private static SimpleDateFormat monthSdf = new SimpleDateFormat("yyyyMM");
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
    private static SimpleDateFormat daySdf = new SimpleDateFormat("yyyyMMdd");
    // 临时用于指定日期范围进行历史数据维护时修改为true，生产环境平时配置为false
    private static boolean reGenerateAllData = false;
    private static final String firstStatMonth = "202301";// 当前若是12月，则维护到前年1.1，否则维护到上前年1.1

    private static HashMap<String, String> rootCustomsMap = new HashMap<String, String>();// 根据关区代码获得所隶属的一级关区代码

    private static List<String> hasMultipleCustomList = new ArrayList<String>(); // 拥有下级关区的关区代码

    private static Set<String> firstClassCustoms = new HashSet<String>(); // 一级关区代码集合

    @Autowired
    private WxjyRepository dao;

    @Autowired
    private PubCustomsMappingRepository mappingRepository;

    @Autowired
    private IedgRepository iedgRepository;

    @Autowired
    private H2018ZhDangerGoodsUtil h2018;

    @Autowired
    private H2018ZhOldDangerGoodsUtil oldH2018;

    @Autowired
    private H2018NewDeclaredGoodsUtil newH2018;

    @Scheduled(cron = "${schedule.cron.h2018.zhDangerGoods}")
    public void h2018DangerData() throws ParseException {
        Calendar c = Calendar.getInstance();
        Date now = c.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //获取危险品的ciq编码
        List<String> ciqCodeList = getCiqCodeList("h2018", "day");
        if (reGenerateAllData) {
            c.setTime(now);
            try {
                // 当前若是12月，则维护到前年1.1，否则维护到上前年1.1 // 要开始维护的后一天开始
                c.setTime(daySdf.parse("20230102"));
            } catch (ParseException e) {
            }
            Date deadline = now;
            try {
                // 截止日期后一天
                deadline = daySdf.parse("20251202");
                logger.info("==========综合危险品通关时长任务执行开始===H2018=====" + sdf.format(new Date()) + "=======");
            } catch (ParseException e) {
            }
            while (!c.getTime().after(deadline)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(c.getTime());
                h2018.h2018Business(ciqCodeList, calendar, "day");
                c.add(Calendar.DATE, 1);
            }
            boolean reGenerateMonthStat = true;// 全新生成所有月度统计
            if (reGenerateMonthStat) {
                logger.info("==========开始维护综合危险品通关时长月度统计中间数据==========");
                rootCustomsMap.clear();
                hasMultipleCustomList.clear();
                firstClassCustoms.clear();
                List<PubCustomsMapping> custMapping = mappingRepository.findAll();
                for (PubCustomsMapping m : custMapping) {
                    String pCustomCode = m.getMappingCode();
                    if (rootCustomsMap.containsValue(pCustomCode)) {
                        hasMultipleCustomList.add(pCustomCode);
                    }
                    rootCustomsMap.put(m.getCustomsCode(), pCustomCode);
                    firstClassCustoms.add(pCustomCode);
                }

                String fromMonthStr = firstStatMonth; // 起始月份
                List<Object[]> list = (List<Object[]>) dao
                        .getQueryBySql("select * from WXJY_MID_D_M_STATUS where STAT_PERIOD = ?", fromMonthStr);
                if (list == null || list.size() == 0) {
                    // 因为UI界面展示设计为可查看最近一年的统计，有些统计需要对比前年的数据，故需要维护最近3-4年的数据
                    now = new Date();
                    Date fromMonth = null;
                    try {
                        fromMonth = monthSdf.parse("202301");
                    } catch (ParseException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    c = Calendar.getInstance();
                    c.setTime(fromMonth);
                    deadline = now;
                    try {
                        deadline = monthSdf.parse("202510");// 截止月份
                    } catch (ParseException e) {
                    }
                    while (!c.getTime().after(deadline)) {
                        String dataPeriod = monthSdf.format(c.getTime());
                        Date statBegin = null;
                        try {
                            statBegin = monthSdf.parse(dataPeriod);
                        } catch (ParseException e) {
                        }
                        c.setTime(statBegin);
                        c.add(Calendar.MONTH, 1);
                        Date statEnd = c.getTime();

                        h2018.monthlyDataMaintance(dataPeriod,statBegin, statEnd);
                    }
                }

                logger.info("完成维护综合危险品通关时长月度统计中间数据");
            }

            return;
        } else {
            //根据上次执行完生成的数据时间接着生成数据
            Date maxEndTime = getEndTime();
            Date deadline = now;
            //如果maxDay为空则代表未生成过数据，则从20200325开始生成，否则就按上次结束时间开始生成
            if (maxEndTime == null) {
                try {
                    // 当前若是12月，则维护到前年1.1，否则维护到上前年1.1// 要开始维护的后一天开始
                    c.setTime(daySdf.parse("20230102"));
                    // 截止日期后一天
                    deadline = daySdf.parse(daySdf.format(now));
                } catch (ParseException e) {
                }
            } else {
                try {
                    // 截止日期后一天
                    deadline = daySdf.parse(daySdf.format(c.getTime()));
                    //从其它系统获取理货时间存在查验数据已经更新但理货时间还未下发情况，所以每天把前一个星期数据重刷避免理货时间下发本系统没赋值
                    //查询出的时间+1天，避免最后那天生成的数据不完整重刷
                    Date day = addDays(maxEndTime, -1);
                    // 要开始维护的后一天开始
                    c.setTime(daySdf.parse(daySdf.format(day)));
                    logger.info("==========任务执行开始===H2018=====" + sdf.format(new Date()) + "=======");
                } catch (ParseException e) {
                }
            }
            while (!c.getTime().after(deadline)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(c.getTime());
                h2018.h2018Business(ciqCodeList, calendar, "day");
                c.add(Calendar.DATE, 1);
            }
        }
        logger.info("==========任务执行结束===H2018=====" + sdf.format(new Date()) + "=======");
    }

    @Scheduled(cron = "${schedule.cron.h2018.zhOldDangerGoods}")
    public void h2018OldDangerData() {
        //捞取新增的检验检疫编码数据
        Calendar c = Calendar.getInstance();
        Date now = c.getTime();
        Date deadline = now;
        try {
            // 当前若是12月，则维护到前年1.1，否则维护到上前年1.1
            c.setTime(daySdf.parse("20230102"));// 要开始维护的后一天开始
            deadline = daySdf.parse(daySdf.format(now));// 截止日期后一天
        } catch (ParseException e) {
        }
        //获取危险品的ciq编码
        List<String> ciqCodeList = getCiqCodeList("h2018", "old");
        while (!c.getTime().after(deadline)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(c.getTime());
            oldH2018.h2018Business(ciqCodeList, calendar, "old");
            c.add(Calendar.DATE, 1);
        }
        logger.info("==========捞取历史任务执行结束===H2018=====" + sdf.format(new Date()) + "=======");

    }

    public static Date addDays(Date date, int day) {
        Calendar currCal = Calendar.getInstance();
        currCal.setTime(date);
        currCal.add(Calendar.DAY_OF_YEAR, day);
        currCal.set(Calendar.HOUR_OF_DAY, 0);
        currCal.set(Calendar.MINUTE, 0);
        currCal.set(Calendar.SECOND, 0);
        return currCal.getTime();
    }

    /**
     * @description: 获取危化品的ciqCode 根据ciqCode获取相关的业务数据
     * @param: dataSource 参数值为eciq或h2018 该参数作为动态字段拼接条件语句
     * @param: businessType old表示当前ciqCode的业务数据还没捞取过需要补捞取历史数据，day表示每天定时捞取至昨日的业务数据
     * @return: java.util.List<java.lang.String>
     * @author zoumin
     * @date: 2021-12-20 11:39:04
     * @version 1.0
     */
    public List<String> getCiqCodeList(String dataSource, String businessType) {
        //用户手动维护的危化品CIQ编码
        String sql = "select distinct c.ciq_code from iedg_sync_chemicals_ciq c ";
        String busColumn = "c.bus_" + dataSource;
        if (businessType.equals("old")) {
            //为空表示查询的是需要补捞历史数据的ciq编码
            sql += "where " + busColumn + " is null ";
        } else if (businessType.equals("day")) {
            //为1表示查询的是每天执行捞取至昨天的ciq编码
            sql += "where " + busColumn + " = '1' ";
        }
        List<String> list = (List<String>) iedgRepository.getQueryBySql(sql);
        return list;
    }

    /**
     * @description: 获取最后一次捞取数据的日期，作为下次捞取数据的开始日期
     * @param: 业务类型，H2018_DANGER_GOODS，ECIQ_DANGER_GOODS，H2018库或ECIQ下发库
     * @return: java.util.Date
     * @author zoumin
     * @date: 2022-03-02 12:35:03
     * @version 1.0
     */
    public Date getEndTime() throws ParseException {
        String endTime = null;
        //执行捞取每天数据的任务，拿到获取数据的结束日期
        String sqlDay = "select max(STAT_PERIOD) from WXJY_MID_D_M_STATUS where DATA_TYPE = 'EntryHead' and business_type = 'day' ";
        String dayDate = (String)dao.getObjectBySql(sqlDay);

        //执行捞取历史数据的任务，拿到获取数据的结束日期
        String sqlOld = "select max(STAT_PERIOD) from WXJY_MID_D_M_STATUS where DATA_TYPE = 'EntryHead' and business_type = 'old' ";
        String oldDate = (String)dao.getObjectBySql(sqlOld);
        //考虑到任务执行过程中会出现异常，所以这里要判断下捞取每天数据的任务和捞取隶属数据的任务最后一次获取数据的日期执行到哪里，
        //从最早的数据结束日期开始捞取数据，尽量避免中间数据漏掉
        if(dayDate != null && oldDate != null){
            //进行比较后，数据结束日期取较早的那个日期作为下次捞取数据的开始日期
            if(daySdf.parse(dayDate).before(daySdf.parse(oldDate))){
                endTime = sdfDate.format(daySdf.parse(dayDate));
            }else{
                endTime = sdfDate.format(daySdf.parse(oldDate));
            }
        }else{
            if(dayDate != null){
                endTime = sdfDate.format(daySdf.parse(dayDate));
            }
            if(oldDate != null){
                endTime = sdfDate.format(daySdf.parse(oldDate));;
            }
        }
        if(endTime != null){
            try {
                return sdfDate.parse(endTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }else{
            return null;
        }
        return null;
    }

    //近一年申报命中查验的新申报商品报关单
    @Scheduled(cron = "${schedule.cron.h2018.newDeclaredGoods}")
    public void h2018NewDeclaredGoodsData() {
        Calendar c = Calendar.getInstance();
        // 时分秒设置为0
        c.set(Calendar.HOUR_OF_DAY, 0); // 时
        c.set(Calendar.MINUTE, 0); // 分
        c.set(Calendar.SECOND, 0); // 秒
        c.set(Calendar.MILLISECOND, 0); // 毫秒
        c.add(Calendar.YEAR, -1);
        String sql = "select distinct cas from IEDG_BASE_CHEMICALS_CATALOG WHERE is_deleted = 0 and cas is not null";
        List<String> list = (List<String>) iedgRepository.getQueryBySql(sql);
        newH2018.toDoDataMain(c.getTime(),list);
        logger.info("==========捞取近一年新申报商品报关单任务执行结束===H2018=====" + sdf.format(new Date()) + "=======");

    }
}
