package com.nokia.tsl_data.service;

import com.alibaba.fastjson2.JSONObject;
import com.nokia.tsl_data.dao.AvgDurationMapperV3;
import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
import com.nokia.tsl_data.dao.TslDataDao;
import com.nokia.tsl_data.dao.WorkFlowBasicDataMapper;
import com.nokia.tsl_data.dao.WorkFlowDao;
import com.nokia.tsl_data.entity.TaskRecord;
import com.nokia.tsl_data.entity.WorkFlowBasicData;
import com.nokia.tsl_data.properties.TslDataProperties;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * 用于所有查询工单流程的任务
 */
@Slf4j
@Service
public class WorkFlowService {

    @Autowired
    private WorkFlowDao workFlowDao;
    @Autowired
    private TslDataDao tslDataDao;
    @Autowired
    private WorkFlowBasicDataMapper workFlowBasicDataMapper;
    @Autowired
    private SysDataDictionaryRepository sysDataDictionaryRepository;
    @Autowired
    private AvgDurationMapperV3 avgDurationMapperV3;
    @Autowired
    private TslDataProperties tslDataProperties;

    private final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
            .withZone(ZoneId.of("Asia/Shanghai"));

    /**
     * 任务名称：更新工作流数据
     */
    public TaskRecord updateWorkFlowBasicData(Instant start, Instant end) {
        TaskRecord record = new TaskRecord();
        record.setTaskName("更新工作流数据");
        JSONObject jsonObject = new JSONObject();
        record.setTaskInfo(jsonObject);
        jsonObject.put("start", dateFormat.format(start));
        jsonObject.put("end", dateFormat.format(end));
        record.setStartTime(Instant.ofEpochMilli(System.currentTimeMillis()));
        try {
            List<WorkFlowBasicData> workFlowBasicDataList = workFlowDao.findWorkFlowBasicDataByUpdateTime(start, end);
            log.debug("从工作流读取到 {} 条数据...", workFlowBasicDataList.size());
            String tempTableName = "tsl_data.work_flow_basic_data_temp_" + System.currentTimeMillis();
            tslDataDao.createTempTableOfWorkFlowBasicData(tempTableName);
            log.debug("创建临时表: {} ...", tempTableName);
            jsonObject.put("tempTableName", tempTableName);
            tslDataDao.batchInsertWorkFlowBasicData(workFlowBasicDataList, tempTableName);
            log.debug("数据已插入临时表 {} ...", tempTableName);
            int insertCount = tslDataDao.insertWorkFlowBasicDataFromTempTable(tempTableName);
            int updateCount = tslDataDao.updateWorkFlowBasicDataFromTempTable(tempTableName);
            log.info("已完成工作流数据更新, 插入 {} 项, 更新 {} 项, 起: {} 止: {}",
                    insertCount, updateCount, dateFormat.format(start), dateFormat.format(end));
            record.setEndStatus(0);
            record.setEndTime(Instant.ofEpochMilli(System.currentTimeMillis()));
        } catch (Exception e) {
            e.printStackTrace();
            record.setEndStatus(-1);
            record.setEndTime(Instant.ofEpochMilli(System.currentTimeMillis()));
        } finally {
            record.setTimeCost(ChronoUnit.MILLIS.between(record.getStartTime(), record.getEndTime()));
        }
        return record;
    }

    /**
     * 超时工单情况
     */
    public List<List<Object>> getTimeoutCountInfo(String day) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date start, end;
        try {
            start = dateFormat.parse(day.substring(0, 6) + "01000000");
            end = dateFormat.parse(day+"235959");
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        List<Map<String, Object>> data = workFlowBasicDataMapper.selectTimeoutTsCountForDay(start, end, tslDataProperties.getDuration());
        Map<String, Map<String, Object>> dayMap = new HashMap<>();
        for (Map<String, Object> map : data) {
            dayMap.put((String) map.get("city"), map);
        }
        List<List<Object>> result = new ArrayList<>();
        // 各地市数据
        for (String area : sysDataDictionaryRepository.findAllCityName()) {
            // 地市 工单数 超时工单数 超时工单占比
            List<Object> list = new ArrayList<>(4);
            result.add(list);
            list.add(0, area);
            // 获取该地市的数据--可能为null
            Map<String, Object> map = dayMap.get(area);
            if (map == null) {
                list.add(1, 0L);
                list.add(2, 0L);
                list.add(3, 0.0);
            } else {
                list.add(1, map.get("total_num"));
                list.add(2, map.get("timeout_num"));
                list.add(3, map.get("timeout_ratio"));
            }
        }
        // 逆序排序
        result.sort((o1, o2) -> Double.compare((double) o2.get(3), (double) o1.get(3)));
        // 全省数据
        List<Object> list = new ArrayList<>();
        result.add(list);
        // 地市
        list.add(0, "全省");
        // 工单数
        list.add(1, dayMap.get("全省").get("total_num"));
        // 超时工单数
        list.add(2, dayMap.get("全省").get("timeout_num"));
        // 超时工单占比
        list.add(3, dayMap.get("全省").get("timeout_ratio"));
        return result;
    }

    /**
     * 平均处理时长
     */
    public List<List<Object>> getCostTimeInfo(String day) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        try {
            calendar.setTime(dateFormat.parse(day));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // 获取上个月的时间
        calendar.add(Calendar.MONTH, -1);
        String oldMonthId = new SimpleDateFormat("yyyyMM").format(calendar.getTime());
        List<Map<String, Object>> oldData = avgDurationMapperV3.selectOldTsDurationForMonth(oldMonthId);
        // 如果上月的平均处理时长数据不存在，需要插入
        if (oldData.size() == 0) {
            avgDurationMapperV3.insertOldTsDurationForMonth(oldMonthId);
            oldData = avgDurationMapperV3.selectOldTsDurationForMonth(oldMonthId);
        }
        // 这里输入的参数格式应为 2014-01-01 00:00:00
        SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyyMMddHHmmss");
        Date start, end;
        try {
            start = dateFormat2.parse(day.substring(0, 6) + "01000000");
            end = dateFormat2.parse(day+"235959");
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        List<Map<String, Object>> dayData = workFlowBasicDataMapper.selectTsDurationForDay(start, end);
        // 转化格式方便读取
        Map<String, Map<String, Object>> dayMap = new HashMap<>();
        Map<String, Map<String, Object>> preMap = new HashMap<>();
        for (Map<String, Object> map : dayData) {
            dayMap.put((String) map.get("city"), map);
        }
        for (Map<String, Object> map : oldData) {
            preMap.put((String) map.get("city_name"), map);
        }
        List<List<Object>> result = new ArrayList<>();
        // 各地市数据
        for (String area : sysDataDictionaryRepository.findAllCityName()) {
            // 地市 上月平均处理时长 当月平均处理时长 涨幅
            List<Object> list = new ArrayList<>(4);
            result.add(list);
            list.add(0, area);
            list.add(1, preMap.get(area).get("avg_duration"));
            Map<String, Object> map = dayMap.get(area);
            if (map == null) {
                list.add(2, 0.0);
                list.add(3, tslDataProperties.getDuration());
                list.add(4, 0.0);
            } else {
                list.add(2, dayMap.get(area).get("avg_duration"));
                list.add(3, tslDataProperties.getDuration());
                // 与目标值差距
                list.add(4, ((double) list.get(2)) - (int) list.get(3));
            }
        }
        // 逆序排序
        result.sort((o1, o2) -> Double.compare((double) o2.get(2), (double) o1.get(2)));
        // 全省数据
        List<Object> allCity = new ArrayList<>(4);
        result.add(allCity);
        allCity.add("全省");
        allCity.add(preMap.get("全省").get("avg_duration"));
        Map<String, Object> map = dayMap.get("全省");
        if (map == null) {
            allCity.add(0.0);
            allCity.add(0.0);
        } else {
            allCity.add(dayMap.get("全省").get("avg_duration"));
            allCity.add(tslDataProperties.getDuration());
            // 修改为与目标差距
            allCity.add((double) allCity.get(2) - (int) allCity.get(3));
        }
        return result;
    }
}
