package cn.edu.whu.boot.statistics.service;


import cn.edu.whu.boot.common.utils.collection.PostgreSqlUtil;
import cn.edu.whu.boot.statistics.bean.CollectorWorkload;
import cn.edu.whu.boot.statistics.bean.ReviewerWorkload;
import cn.edu.whu.boot.statistics.bean.UserWorkload;
import cn.edu.whu.boot.statistics.mapper.CollectorMapper;
import cn.edu.whu.boot.statistics.mapper.ProgressStatMapper;
import cn.edu.whu.boot.user.entities.User;
import cn.edu.whu.boot.user.services.UserService;
import cn.edu.whu.boot.xml.domain.Task;
import cn.edu.whu.boot.xml.service.ITaskService;
import cn.edu.whu.boot.xml.xmlreader.XmlTemplateReader;
import cn.edu.whu.boot.xml.xmlreader.bean.Config;
import cn.edu.whu.boot.xml.xmlreader.bean.Table;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ReportService {

    @Autowired
    ProgressStatMapper progressStatMapper;

    @Autowired
    CollectorMapper collectorMapper;

    @Autowired
    ITaskService taskService;

    @Autowired
    UserService userService;

    @Value("#{'${XmlFilePath}' + '/'}")
    private String XML_FOLDER;

    /**
     * 获取该 task 下的所有地理信息表
     *
     * @param taskId
     * @return
     */
    private Map<String, Table> getTables(int taskId) {
        String fileName = progressStatMapper.getTaskXmlNameById(taskId);
        String path = XML_FOLDER + fileName + ".xml";
        Config config = XmlTemplateReader.read(path);

        // 获取存储有地理信息的表
        return config.getRootTables();
    }


    /**
     * 统计 task 下地理信息表的相关信息
     *
     * @param taskId
     * @return
     */
    public JSONArray featuresInfo(int taskId) {
        JSONArray result = new JSONArray();

        //1. 获取 task 对应的数据库名称
        String taskDBName = progressStatMapper.getTaskDBNameById(taskId);

        //2. 获取该 task 下的所有根表 ，即所有地理属性的表
        Map<String, Table> rootTbls = getTables(taskId);

        //3. 对所有的地理信息表做遍历统计
        for (String key : rootTbls.keySet()) {
            String tblName = '"' + taskDBName + '"' + "." + '"' + key + '"';
            JSONObject featureInfo = new JSONObject(true);
            featureInfo.put("name", key);
            featureInfo.put("name_ch", rootTbls.get(key).getName());
            // 数据总量
            featureInfo.put("count", progressStatMapper.getCount(tblName));

            featureInfo.put("statDaily", statDaily(tblName));

            featureInfo.put("statMonthly", statMonthly(tblName));


            result.add(featureInfo);
        }

        return result;
    }


    private JSONObject statDaily(String tblName) {

        JSONObject result = new JSONObject(true);

        List<HashMap<String, Long>> data = collectorMapper.statDaily(tblName);

        double avg = 0;
        int sum = 0;
        int size = data.size();
        long max = Integer.MIN_VALUE;
        long min = Integer.MAX_VALUE;
        String maxDay = null;
        String minDay = null;
        HashMap<String, Long> maxMap = new HashMap<>();
        HashMap<String, Long> minMap = new HashMap<>();

        for (Iterator iterator = data.iterator(); iterator.hasNext(); ) {
            HashMap dayRecord = (HashMap) iterator.next();
            String date = (String) dayRecord.get("date");
            long count = (long) dayRecord.get("count");
            if (count >= max) {
                max = count;
                maxDay = date;
            }

            if (count <= min) {
                min = count;
                minDay = date;
            }
            sum += count;
        }

        // 每日采集的均值
        result.put("avg", (double) sum / size);
        // 按日统计
        result.put("data", data);
        // 按日统计比例
        result.put("ratio", collectorMapper.statDailyRatio(tblName));
        // 采集最多的一天与采集最少的一天
        if (maxDay == null) {
            maxMap.put("无数据", 0L);
        } else {
            maxMap.put(maxDay, max);
        }

        if (minDay == null) {
            minMap.put("无数据", 0L);
        } else {
            minMap.put(minDay, min);
        }
        result.put("maxDay", maxMap);
        result.put("minDay", minMap);

        return result;
    }

    private JSONObject statMonthly(String tblName) {

        JSONObject result = new JSONObject(true);

        List<HashMap<String, Long>> data = collectorMapper.statMonthly(tblName);

        double avg = 0;
        int sum = 0;
        int size = data.size();
        long max = Integer.MIN_VALUE;
        long min = Integer.MAX_VALUE;
        String maxMonth = null;
        String minMonth = null;

        HashMap<String, Long> maxMap = new HashMap<>();
        HashMap<String, Long> minMap = new HashMap<>();

        for (Iterator iterator = data.iterator(); iterator.hasNext(); ) {
            HashMap monthRecord = (HashMap) iterator.next();
            String date = (String) monthRecord.get("date");
            long count = (long) monthRecord.get("count");
            if (count >= max) {
                max = count;
                maxMonth = date;
            }

            if (count <= min) {
                min = count;
                minMonth = date;
            }
            sum += count;
        }

        // 每月采集的均值
        result.put("avg", (double) sum / size);
        // 按月统计
        result.put("data", data);
        // 按月统计比例
        result.put("ratio", collectorMapper.statMonthlyRatio(tblName));
        // 采集最多的一月与采集最少的一月
        if (maxMonth == null) {
            maxMap.put("无数据", 0L);
        } else {
            maxMap.put(maxMonth, max);
        }

        if (minMonth == null) {
            minMap.put("无数据", 0L);
        } else {
            minMap.put(minMonth, min);
        }

        result.put("maxMonth", maxMap);
        result.put("minMonth", minMap);

        return result;

    }

    public JSONArray collectorsInfo(int taskId) {
        JSONArray result = new JSONArray();

        String taskDBName = progressStatMapper.getTaskDBNameById(taskId);
//        int taskId = collectorMapper.getTaskId(tskName);

        // 1. 获取参与该任务的所有人员
        List<User> workers = taskService.getWorkersByTask(taskId);

        // 2. 获取该任务的所有地理信息表
        Map<String, Table> rootTbls = getTables(taskId);

        for (User worker : workers) {

            JSONObject workerInfo = new JSONObject(true);
            workerInfo.put("name", worker.getUsername());
            workerInfo.put("phone", worker.getPhone());
            workerInfo.put("email", worker.getEmail());

            for (Map.Entry entry : rootTbls.entrySet()) {

                String tblName = '"' + taskDBName + '"' + "." + '"' + entry.getKey() + '"';
                Table table = (Table) entry.getValue();
                workerInfo.put(table.getName(), statCollectorInfo(tblName, worker));

            }

            result.add(workerInfo);

        }

        return result;
    }

    private JSONObject statCollectorInfo(String tblName, User collector) {
        JSONObject result = new JSONObject(true);

        // 1.获取采集的点总数
        int workLoad = collectorMapper.getCollectorWorkLoad(tblName, collector.getId());

        // 2.获取某个人按天统计的工作量
        List<HashMap> workLoadDaily = collectorMapper.getCollectorWorkLoadDaily(tblName, collector.getId());

        // 3.每天的平均工作量
        double avgWorkLoad = (workLoadDaily.size() != 0) ? workLoad / workLoadDaily.size() : 0;

        result.put("workLoad", workLoad);
        result.put("avgWorkLoad", avgWorkLoad);
        result.put("workLoadDaily", workLoadDaily);
        return result;
    }

    public List<UserWorkload> countWorkloadByUser(int taskId) {
        Map<Integer, UserWorkload> id2workload = new HashMap<>();
        // 获取该任务下所有的工作人员
        List<User> workers = taskService.getWorkersByTask(taskId);
        if (workers.isEmpty()) {
            return Collections.emptyList();
        }
        for (User worker : workers) {
            id2workload.put(worker.getId(), new UserWorkload(worker.getRealName()));
        }

        Task task = taskService.getTaskById(taskId);
        Map<String, Table> tables = JSON.toJavaObject(JSON.parseObject(task.getConfig()), Config.class).getRootTables();
        for (String tableName : tables.keySet()) {
            String tb = PostgreSqlUtil.buildTableNameString(task.getDatabaseName(), tableName, false, false);
            // 统计每个工作人员分配到的任务量、巡查上传后待审核的数据量、通过审核的数据量和未通过审核的数据量，以及额外新采集的数据量
            for (ReviewerWorkload rw : collectorMapper.countWorkloadByReviewer(tb)) {
                UserWorkload workload = id2workload.computeIfAbsent(rw.getUser(), id -> new UserWorkload(userService.findRealNameById(id)));
                workload.incrementReviewerTotalWorkload(rw.getTotalWorkload());
                workload.incrementToBeReviewedDataCount(rw.getToBeReviewedDataCount());
                workload.incrementValidDataCount(rw.getValidDataCount());
                workload.incrementInvalidDataCount(rw.getInvalidDataCount());
                workload.incrementCollectedDataCount(workload.getToBeReviewedDataCount() + workload.getInvalidDataCount() + workload.getValidDataCount());
            }
            for (CollectorWorkload cw : collectorMapper.countWorkloadByCollector(tb)) {
                id2workload.computeIfAbsent(cw.getUser(), id -> new UserWorkload(userService.findRealNameById(id))).incrementNewDataCount(cw.getNewDataCount());
            }
        }
        return new ArrayList<>(id2workload.values());
    }
}
