package com.mooctest.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mooctest.dao.SupplementDao;
import com.mooctest.model.SupplementItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Service
public class GraphService {

    @Autowired
    SupplementDao supplementDao;

    public JSONObject buildAggReportTree(String masterId) {
        List<SupplementItem> supplementItems = supplementDao.findByMasterId(masterId);
        Map<String, List<SupplementItem>> supplementMap = supplementItems.stream()
                .collect(groupingBy(SupplementItem::getSupplementId));

        JSONObject root = new JSONObject();
        root.fluentPut("id", "agg_" + masterId)
                .fluentPut("group", 1)
                .fluentPut("name", "聚合报告")
                .fluentPut("href", "/graphDetail/aggReport?masterId=" + masterId);
        int idx = 1;

        JSONArray supNodes = new JSONArray();
        //add sup correspond with raw node
        for (Map.Entry<String, List<SupplementItem>> entry : supplementMap.entrySet()) {
            String supId = entry.getKey();
            List<SupplementItem> items = entry.getValue();
            JSONObject supNode = new JSONObject();

            //add sup report node
            supNode.fluentPut("id", supId)
                    .fluentPut("group", 2)
                    .fluentPut("name", "补充点" + idx)
                    .fluentPut("href", "/graphDetail/supReport?supId=" + supId + "&masterId=" + masterId);
            supNodes.add(supNode);

            //add raw report node
            List<String> bugIds = items.stream()
                    .map(SupplementItem::getBugId)
                    .distinct()
                    .collect(Collectors.toList());

            JSONArray rawNodes = new JSONArray();
            for (int i = 0; i < bugIds.size(); i++) {
                String bugId = bugIds.get(i);
                JSONObject rawNode = new JSONObject();
                rawNode.fluentPut("id", bugId)
                        .fluentPut("group", 3)
                        .fluentPut("name", "R" + bugId.substring(12))
                        .fluentPut("href", "/graphDetail/rawReport?bugId=" + bugId + "&masterId=" + masterId);
                rawNodes.add(rawNode);
            }
            supNode.put("children", rawNodes);
            idx++;
        }
        root.put("children", supNodes);
        return root;
    }

    public JSONObject buildAggReportGraph(String masterId) {
        List<SupplementItem> supplementItems = supplementDao.findByMasterId(masterId);
        Map<String, List<SupplementItem>> supplementMap = supplementItems.stream()
                .collect(groupingBy(SupplementItem::getSupplementId));

        JSONObject graphNodes = new JSONObject();
        JSONArray nodes = buildNodes(masterId, supplementMap);
        graphNodes.put("nodes", nodes);

        JSONArray links = buildLinks(masterId, supplementMap);
        graphNodes.put("links", links);

        return graphNodes;
    }

    private JSONArray buildLinks(String masterId, Map<String, List<SupplementItem>> supplementMap) {
        JSONArray links = new JSONArray();
        String aggReportId = "agg_" + masterId;
        supplementMap.forEach((supId, items) -> {

            JSONObject supAggLink = new JSONObject();
            supAggLink.fluentPut("source", supId)
                    .fluentPut("target", aggReportId)
                    .fluentPut("value", 3);
            links.add(supAggLink);

            items.forEach(item -> {
                JSONObject bugSupLink = new JSONObject();
                bugSupLink.fluentPut("source", item.getBugId())
                        .fluentPut("target", supId)
                        .fluentPut("value", 1);
                links.add(bugSupLink);
            });
        });

        JSONObject masterAggLink = new JSONObject();
        masterAggLink.fluentPut("source", masterId)
                .fluentPut("target", aggReportId)
                .fluentPut("value", 2);
        links.add(masterAggLink);
        return links;
    }

    private JSONArray buildNodes(String masterId, Map<String, List<SupplementItem>> supplementMap) {

        JSONArray nodes = new JSONArray();
        int idx = 0;

        //add sup correspond with raw node
        for (Map.Entry<String, List<SupplementItem>> entry : supplementMap.entrySet()) {
            String supId = entry.getKey();
            List<SupplementItem> items = entry.getValue();
            JSONObject node = new JSONObject();

            //add sup report node
            node.fluentPut("id", supId)
                    .fluentPut("group", 2)
                    .fluentPut("name", "Sup-" + idx)
                    .fluentPut("href", "/graphDetail/supReport?supId=" + supId + "&masterId=" + masterId);
            nodes.add(node);

            //add raw report node
            List<String> bugIds = items.stream()
                    .map(SupplementItem::getBugId)
                    .distinct()
                    .collect(Collectors.toList());

            for (int i = 0; i < bugIds.size(); i++) {
                String bugId = bugIds.get(i);
                JSONObject rawNode = new JSONObject();
                rawNode.fluentPut("id", bugId)
                        .fluentPut("group", 6)
                        .fluentPut("name", "ML-" + bugId.substring(10))
                        .fluentPut("href", "/graphDetail/rawReport?bugId=" + bugId + "&masterId=" + masterId);
                nodes.add(rawNode);
            }
            idx++;
        }
        JSONObject aggReportNode = new JSONObject();
        aggReportNode.fluentPut("id", "agg_" + masterId)
                .fluentPut("group", 1)
                .fluentPut("name", "ML-AG-" + masterId.substring(10))
                .fluentPut("href", "/graphDetail/aggReport?masterId=" + masterId);
        nodes.add(aggReportNode);

        JSONObject masterNode = new JSONObject();
        masterNode.fluentPut("id", masterId)
                .fluentPut("group", 2.1)
                .fluentPut("name", "Master-ML-" + masterId.substring(10))
                .fluentPut("href", "/graphDetail/rawReport?bugId=" + masterId + "&isMaster=true" + "&masterId=" + masterId);
        nodes.add(masterNode);

        return nodes;
    }

}
