package com.nokia.tsl_data.service;

import com.nokia.tsl_data.dao.AvgDurationMapperV3;
import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
import com.nokia.tsl_data.dao.WorkFlowDao;
import com.nokia.tsl_data.properties.TslDataProperties;

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.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

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

    @Autowired
    private WorkFlowDao workFlowDao;
    @Autowired
    private SysDataDictionaryRepository sysDataDictionaryRepository;
    @Autowired
    private AvgDurationMapperV3 avgDurationMapperV3;
    @Autowired
    private TslDataProperties tslDataProperties;

    private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
            .withZone(ZoneId.of("Asia/Shanghai"));

    /**
     * 超时工单情况
     * 20240205更新
     */
    public List<List<Object>> getTimeoutCountInfo(String day) {
        Instant start = Instant.from(dateTimeFormatter.parse(day.substring(0, 6) + "01000000"));
        Instant end = Instant.from(dateTimeFormatter.parse(day + "235959"));
        List<Map<String, Object>> data = getTimeoutTsCountForDay(start, end);
        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;
    }

    /**
     * 平均处理时长
     * 20240205更新 20240304更新
     */
    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) {
            List<Map<String, Object>> tsDurationForMonth = getTsDurationForMonth(oldMonthId);
            for (Map<String, Object> map : tsDurationForMonth) {
                avgDurationMapperV3.insertOne(map);
            }
            oldData = avgDurationMapperV3.selectOldTsDurationForMonth(oldMonthId);
        }
        Instant start = Instant.from(dateTimeFormatter.parse(day.substring(0, 6) + "01000000"));
        Instant end = Instant.from(dateTimeFormatter.parse(day + "235959"));
        List<Map<String, Object>> dayData = getTsDurationForDay(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;
    }

    private List<Map<String, Object>> getTimeoutTsCountForDay(Instant start, Instant end) {
        Map<String, String> workFlowCityMap = sysDataDictionaryRepository.findWorkFlowCityMap();
        List<Map<String, Object>> selectTimeoutTsCountForDay = workFlowDao.selectTimeoutTsCountForDayV2(start, end);
        for (Map<String, Object> map : selectTimeoutTsCountForDay) {
            String city_id = (String) map.get("city_id");
            if (city_id.equals("全省")) {
                map.put("city", "全省");
            } else {
                map.put("city", workFlowCityMap.get(city_id));
            }
        }
        return selectTimeoutTsCountForDay;
    }

    private List<Map<String, Object>> getTsDurationForDay(Instant start, Instant end) {
        Map<String, String> workFlowCityMap = sysDataDictionaryRepository.findWorkFlowCityMap();
        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                .withZone(ZoneId.of("Asia/Shanghai"));
        List<Map<String, Object>> selectTsDurationForDay = workFlowDao
                .selectTsDurationForDayV2(dateFormat.format(start), dateFormat.format(end));
        for (Map<String, Object> map : selectTsDurationForDay) {
            String city_id = (String) map.get("city_id");
            if (city_id.equals("全省")) {
                map.put("city", "全省");
            } else {
                map.put("city", workFlowCityMap.get(city_id));
            }
        }
        return selectTsDurationForDay;
    }

    public List<Map<String, Object>> getTsDurationForMonth(String month) {
        Map<String, String> workFlowCityMap = sysDataDictionaryRepository.findWorkFlowCityMap();
        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                .withZone(ZoneId.of("Asia/Shanghai"));
        String start = month.substring(0, 4) + "-" + month.substring(4, 6) + "-01 00:00:00";
        String end = LocalDateTime.parse(start, dateFormat).plusMonths(1).format(dateFormat);
        List<Map<String, Object>> result = workFlowDao.selectTsDurationForDayV2(start, end);
        for (Map<String, Object> map : result) {
            map.put("month_id", month);
            String city_id = (String) map.get("city_id");
            if (city_id.equals("全省")) {
                map.put("city", "全省");
            } else {
                map.put("city", workFlowCityMap.get(city_id));
            }
        }
        return result;
    }
}
