package com.nokia.tsl_data.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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

import com.nokia.tsl_data.dao.ManagementDetailMapper;
import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
import com.nokia.tsl_data.dao.TargetTsRatioMapper;
import com.nokia.tsl_data.exception.LackOfDataRuntimeException;
import com.nokia.tsl_data.util.DateFormatUtil;

/**
 * 2024年适配需求
 */
@Service
public class ManagementDetailService {

    @Autowired
    private ManagementDetailMapper managementDetailMapper;
    @Autowired
    private SysDataDictionaryRepository sysDataDictionaryRepository;
    @Autowired
    private TargetTsRatioMapper targetTsRatioRepository;
    @Autowired
    private UserCountService userCountService;

    /**
     * 检查数据源
     */
    public void checkDataSource(String day) {
        if (managementDetailMapper.selectAllForMonth(day) == 0) {
            throw new RuntimeException("management_detail 表缺少账期 " + day + " 数据...");
        }
    }

    /**
     * 生成某个帐期的数据
     */
    public void generateForDay(String day) {
        if (managementDetailMapper.selectCountofStatDay(day) != 0) {
            throw new RuntimeException("managementDetail 帐期 " + day + " 已存在数据...");
        }
        managementDetailMapper.insertFromMobileComplaint(day);
        managementDetailMapper.insertFromComplaintDetailsFixYwd(day);
    }

    /**
     * 2024年适配需求 统计数据在原有基础（河北_CEM移网质量投诉明细全量数据）上增加新订阅的 河北客户体验管理智能定责投诉明细月累计接口日 表中
     * 日定责问题分类(duty_reason_id_day) 字段值为 业务使用>>基础业务使用>>移网主被叫>>手机无法主被叫 的部分。
     */
    public Map<String, List<Object>> getSheet1DataV3(String day) {
        // 1. 初始化存储
        Map<String, List<Object>> result = new HashMap<>();
        // dayIndex 决定每个List需要初始化多少元素(确实存在某一个某个地市数量为0的情况，这种情况数据库取到的可能没值，通过初始化可以避免缺失)
        int dayIndex = Integer.parseInt(day.substring(6, 8));
        // 初始化每个地市（按固定顺序）每天的工单量
        for (String area : sysDataDictionaryRepository.findAllCityName()) {
            List<Object> list = new ArrayList<>();
            for (int i = 0; i < dayIndex; i++) {
                list.add(0);
            }
            result.put(area, list);
        }
        // 初始化全省每天工作量
        List<Object> list0 = new ArrayList<>();
        for (int i = 0; i < dayIndex; i++) {
            list0.add(0);
        }
        result.put("全省", list0);
        // 2. 读取数据库数据(工单数量)并写入结果
        // 各地市每日投诉量
        List<Map<String, Object>> cityTslForMonth = managementDetailMapper.selectCityTslForMonth(day);
        for (Map<String, Object> map : cityTslForMonth) {
            int dayId = Integer.parseInt(map.get("day_id").toString());
            // 注意这里用的是赋值而不是add
            result.get(map.get("compl_area_local").toString()).set(dayId - 1, map.get("num"));
        }
        List<Map<String, Object>> allTslForMonth = managementDetailMapper.selectAllTslForMonth(day);
        // 全省每日投诉量
        for (Map<String, Object> map : allTslForMonth) {
            int dayId = Integer.parseInt(map.get("day_id").toString());
            result.get("全省").set(dayId - 1, map.get("num"));
        }
        // 各地市投诉总数
        List<Map<String, Object>> cityAllForMonth = managementDetailMapper.selectCityAllForMonth(day);
        // 各地市投诉总量
        for (Map<String, Object> map : cityAllForMonth) {
            result.get(map.get("compl_area_local").toString()).add(map.get("num"));
        }
        // 全省总量
        int total = managementDetailMapper.selectAllForMonth(day);
        result.get("全省").add(total);
        // 3. 读取数据库 当月管理端用户数
        Map<String, Double> userCount = userCountService.getManagementUserCountForMonth(day.substring(0, 6));
        // 管理端用户数写入结果
        for (Entry<String, List<Object>> entry : result.entrySet()) {
            entry.getValue().add(userCount.get(entry.getKey()));
        }
        // 4. 万投率和本月预测
        Calendar calendar = DateFormatUtil.toCalendar(day, "yyyyMMdd");
        for (Entry<String, List<Object>> entry : result.entrySet()) {
            List<Object> list = entry.getValue();
            int size = list.size();
            // 计算万投率
            double wtl = Double.parseDouble(list.get(size - 2).toString())
                    / Double.parseDouble(list.get(size - 1).toString());
            list.add(wtl);
            // 计算预测万投率
            double ycwtl = wtl * calendar.getActualMaximum(Calendar.DAY_OF_MONTH) / calendar.get(Calendar.DAY_OF_MONTH);
            list.add(ycwtl);
        }
        // 5. 期望万投率
        List<Map<String,Object>>  targetTsRatios = targetTsRatioRepository.findByMonthId(day.substring(0, 6));
        for (Map<String,Object> targetTsRatio : targetTsRatios) {
            result.get(targetTsRatio.get("city_name").toString()).add(targetTsRatio.get("management_target_ratio"));
        }
        // 6. 与目标差距
        for (Entry<String, List<Object>> entry : result.entrySet()) {
            List<Object> list = entry.getValue();
            int size = list.size();
            double cj = ((double) list.get(size - 2)) - ((double) list.get(size - 1));
            list.add(cj);
        }
        return result;
    }

    /**
     * 按照账期检查数据
     */
    public void checkStatDayCount(String day) {
        int count = managementDetailMapper.selectCountofStatDay(day);
        if (count == 0) {
            throw new LackOfDataRuntimeException(String.format("management_detail 表缺少账期 %s 数据", day));
        }
    }

    /**
     * 重复投诉
     */
    public List<List<Object>> getRepeatTsDataV3(String day) {
        // 从数据库
        List<Map<String, Object>> dayData = managementDetailMapper.selectRepeatTsCountForDay(day);
        List<Map<String, Object>> preDayData = dayData;
        if (!day.endsWith("01")) {
            String preDay = String.valueOf(Integer.parseInt(day) - 1);
            preDayData = managementDetailMapper.selectRepeatTsCountForDay(preDay);
        }
        // 转化格式方便读取
        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("compl_area_local"), map);
        }
        for (Map<String, Object> map : preDayData) {
            preMap.put((String) map.get("compl_area_local"), map);
        }
        List<List<Object>> result = new ArrayList<>();
        // 各地市数据
        for (String area : sysDataDictionaryRepository.findAllCityName()) {
            List<Object> list = new ArrayList<>(7);
            result.add(list);
            list.add(0, area);
            // 重复投诉工单数
            list.add(1, preMap.get(area).get("repeat_num"));
            list.add(2, dayMap.get(area).get("repeat_num"));
            // 重复投诉率
            list.add(3, preMap.get(area).get("repeat_ratio"));
            list.add(4, dayMap.get(area).get("repeat_ratio"));
            // 增量
            list.add(5, ((double) list.get(2)) - ((double) list.get(1)));
            list.add(6, ((double) list.get(4)) - ((double) list.get(3)));
        }
        // 排序--逆序
        result.sort((o1, o2) -> Double.compare((double) o2.get(6), (double) o1.get(6)));
        // 全省数据
        List<Object> list = new ArrayList<>(7);
        result.add(list);
        list.add(0, "全省");
        // 重复投诉工单数
        list.add(1, preMap.get("全省").get("repeat_num"));
        list.add(2, dayMap.get("全省").get("repeat_num"));
        // 重复投诉率
        list.add(3, preMap.get("全省").get("repeat_ratio"));
        list.add(4, dayMap.get("全省").get("repeat_ratio"));
        // 增量
        list.add(5, ((double) list.get(2)) - ((double) list.get(1)));
        list.add(6, ((double) list.get(4)) - ((double) list.get(3)));
        return result;
    }

}
