package com.xhkjedu.sapi.service.region;

import com.xhkjedu.sapi.mapper.region.SAnalyzeMapper;
import com.xhkjedu.sapi.mapper.system.SchoolMapper;
import com.xhkjedu.sapi.vo.analyze.SchoolParams;
import com.xhkjedu.sapi.vo.region.*;
import com.xhkjedu.utils.N_Utils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ywx
 * @classname SAnalyzeService
 * @description 
 * @date 2021/6/24 11:06
 **/
@Service
public class SAnalyzeService {
    @Resource
    private SAnalyzeMapper sAnalyzeMapper;
    @Resource
    private SchoolMapper schoolMapper;

    //获取资源类型统计
    public Map listResourceTypeNum(Integer schoolid, String type) {
        Map map = new HashMap();

        List<ResourceTypeVo> lst;
        if (type.equals("resource")) {//资源类型统计
            lst = sAnalyzeMapper.listResourceTypeNum(schoolid);
        } else {//试题科目统计
            lst = sAnalyzeMapper.listQuestionSubjectNum(schoolid);
        }
        Integer totalnum = 0;

        if (lst != null && lst.size() > 0) {
            totalnum = lst.stream().mapToInt(ResourceTypeVo::getRnum).sum();

            ResourceTypeVo maxtype = lst.stream().max(Comparator.comparing(ResourceTypeVo::getRnum)).get();//最高的类型
            double maxtyperate = N_Utils.getIntegerDivideAndMulitiply(maxtype.getRnum(), totalnum);

            //处理平台资源和校本资源
            Integer ptnum = lst.stream().mapToInt(ResourceTypeVo::getPtnum).sum();
            Integer xbnum = lst.stream().mapToInt(ResourceTypeVo::getXbnum).sum();
            double ptrate = N_Utils.getIntegerDivideAndMulitiply(ptnum, totalnum);
            double xbrate = N_Utils.getIntegerDivideAndMulitiply(xbnum, totalnum);

            List<Map> tmlst = setResources(lst);

            map.put("rtypes", tmlst);//类型
            if (type.equals("resource")) map.put("maxtype", maxtype.getRtype());
            if (type.equals("question")) map.put("maxtype", maxtype.getSubjectname());
            map.put("maxnum", maxtype.getRnum());
            map.put("maxrate", maxtyperate);
            map.put("ptrate", ptrate);
            map.put("xbrate", xbrate);
        }

        map.put("totalnum",totalnum);
        return map;
    }

    //获取资源格式统计
    public List<Map> listResourceClassNum(Integer schoolid) {
        List<ResourceTypeVo> lst = sAnalyzeMapper.listResourceClassNum(schoolid);
        return setResources(lst);
    }

    //获取资源科目统计
    public List<Map> listResourceSubjectNum(Integer schoolid) {
        List<ResourceTypeVo> lst = sAnalyzeMapper.listResourceSubjectNum(schoolid);
        return setResources(lst);
    }

    //计算比例
    private List<Map> setResources(List<ResourceTypeVo> lst) {
        Integer totalnum = 0;
        if (lst != null && lst.size() > 0) {
            totalnum = lst.stream().mapToInt(ResourceTypeVo::getRnum).sum();
        }
        List<Map> tmlst = new ArrayList<>();
        for (ResourceTypeVo rt : lst) {
            Map tmap = new HashMap();
            double srate = N_Utils.getIntegerDivideAndMulitiply(rt.getRnum(), totalnum);
            Integer rtype = rt.getRtype();
            if (!N_Utils.isEmptyInteger(rtype)) tmap.put("rtype", rtype);
            tmap.put("rnum", rt.getRnum());
            tmap.put("rrate", srate);
            String subjectname = rt.getSubjectname();
            if (N_Utils.isNotEmpty(subjectname)) tmap.put("rtype",subjectname);
            tmlst.add(tmap);
        }
        return tmlst;
    }

    //获取班级、教师、学生总量
    public Map listClassTeacherStudentNum(SchoolParams param) {
//        Map map = sAnalyzeMapper.listClassTeacherStudentNum(schoolid);
        Map map = new HashMap();
        if(N_Utils.isEmptyInteger(param.getYear())){
            param.setYear(schoolMapper.getYearById(param.getSchoolid()));
        }
        List<Map> list = sAnalyzeMapper.listClassTeacherStudent(param);
        Map<Integer,List<Map>> grades = list.stream().collect(Collectors.groupingBy(m->(Integer) m.get("gradeid")));
        grades = grades.entrySet().stream().sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (c1, c2) -> c1, LinkedHashMap::new));
        List<Map> glist = new ArrayList<>();
        List<SAClassVo> clist = new ArrayList<>();
        for(Map.Entry gmap:grades.entrySet()) {
            Object gradeid = gmap.getKey();
            List<Map> ctslist = (List<Map>) gmap.getValue();
            Map<Integer,List<Map>> classes = ctslist.stream().collect(Collectors.groupingBy(m->(Integer) m.get("classid")));
            for(Map.Entry cmap:classes.entrySet()) {
                List<Map> tslist = (List<Map>) cmap.getValue();
                Map<Integer,List<Map>> teachers = tslist.stream().filter(m-> N_Utils.isNotEmpty(m.get("teacherid")))
                        .collect(Collectors.groupingBy(m->(Integer) m.get("teacherid")));
                Map<Integer,List<Map>> students = tslist.stream().filter(m-> N_Utils.isNotEmpty(m.get("studentid")))
                        .collect(Collectors.groupingBy(m->(Integer) m.get("studentid")));
                List<Map> sexlist = new ArrayList<>();
                int jsnum = teachers.size();
                Map<Object,List<Map>> users = tslist.stream().filter(m-> N_Utils.isNotEmpty(m.get("studentid"))).collect(Collectors.groupingBy(m->m.get("usersex")));
                for(Map.Entry sexmap:users.entrySet()) {
                    Map sex = new HashMap();
                    sex.put("usersex",sexmap.getKey());
                    Integer usernum = ((List<Map>) sexmap.getValue()).size();
                    if (jsnum!=0) usernum = usernum/jsnum;
                    sex.put("usernum",usernum);
                    sexlist.add(sex);
                }
                SAClassVo c = new SAClassVo();
                c.setGradeid((Integer) gradeid);
                c.setClassid((Integer) cmap.getKey());
                Map map1 = tslist.get(0);
                c.setClassname((String) map1.get("classname"));
                c.setClassorder((Integer) map1.get("classorder"));
                c.setJsnum(jsnum);
                c.setXsnum(students.size());
                c.setSexlist(sexlist);
                clist.add(c);
            }
            Map g = new HashMap();
            g.put("gradeid",gradeid);
            g.put("bjnum",classes.size());
            Integer jsnum = ctslist.stream().filter(m-> N_Utils.isNotEmpty(m.get("teacherid")))
                    .collect(Collectors.groupingBy(m->(Integer) m.get("teacherid"))).size();
            g.put("jsnum",jsnum);
            Integer xsnum = ctslist.stream().filter(m-> N_Utils.isNotEmpty(m.get("studentid")))
                    .collect(Collectors.groupingBy(m->(Integer) m.get("studentid"))).size();
            g.put("xsnum",xsnum);
            g.put("zsnum",jsnum+xsnum);
            glist.add(g);
        }
        Integer jsnum = list.stream().filter(m-> N_Utils.isNotEmpty(m.get("teacherid")))
                .collect(Collectors.groupingBy(m->(Integer) m.get("teacherid"))).size();
        map.put("jsnum",jsnum);
        Integer xsnum = list.stream().filter(m-> N_Utils.isNotEmpty(m.get("studentid")))
                .collect(Collectors.groupingBy(m->(Integer) m.get("studentid"))).size();
        map.put("xsnum",xsnum);
        map.put("ssbl", N_Utils.getFs(jsnum,xsnum));
        Integer bjnum = list.stream().collect(Collectors.groupingBy(m->(Integer) m.get("classid"))).size();
        map.put("bjnum",bjnum);
        map.put("grades",glist);
        clist = clist.stream().sorted(Comparator.comparing(SAClassVo::getGradeid).thenComparing(SAClassVo::getClassorder)).collect(Collectors.toList());
        map.put("classes",clist);
        return map;
    }

    //近一个月访问量统计
    public Map listAccess(Integer schoolid, Integer begintime, Integer endtime) {
        List<AccessVo> access = sAnalyzeMapper.listAccess(schoolid , begintime, endtime);
        return getLogMonitor(access,"access");
    }

    //近一个月应用监控统计
    public Map listAppMonitorMonth(Integer schoolid, Integer begintime, Integer endtime) {
        List<AccessVo> access = sAnalyzeMapper.listAppMonitorMonth(schoolid , begintime, endtime);
        return getLogMonitor(access,"monitor");
    }

    private Map getLogMonitor(List<AccessVo> access,String type) {
        Map map = new HashMap();
        Integer maxnum = 0;
        Integer totalnum = 0;
        String ultype = null;
        if (access != null && access.size() > 0) {
            if (type.equals("access")) {
                Map<String, List<AccessVo>> access2 = access.stream().collect(Collectors.groupingBy(a -> a.getLogtime()));
                access = new ArrayList<>();
                for(Map.Entry amap:access2.entrySet()) {
                    List<AccessVo> list = (List<AccessVo>) amap.getValue();
                    AccessVo a1 = new AccessVo();
                    a1.setLogtime((String) amap.getKey());
                    Integer num = list.stream().collect(Collectors.summingInt(a -> a.getNum()));
                    a1.setNum(num);
                    Map<String, List<AccessVo>> list2 = list.stream().collect(Collectors.groupingBy(a -> a.getUltype()));
                    List<Map> ultypes = new ArrayList<>();
                    for(Map.Entry umap:list2.entrySet()) {
                        Map a = new HashMap();
                        List<AccessVo> ultypes2 = (List<AccessVo>) umap.getValue();
                        a.put("num",ultypes2.stream().collect(Collectors.summingInt(u->u.getNum())));
                        a.put("ultype",umap.getKey());
                        ultypes.add(a);
                    }
                    a1.setUltypes(ultypes);
                    access.add(a1);
                }
                totalnum = access.stream().collect(Collectors.summingInt(AccessVo::getNum));
            } else {
                totalnum = access.stream().collect(Collectors.summingInt(AccessVo::getNum));
                for (AccessVo a : access) {
                    a.setNumrate(N_Utils.getIntegerDivideAndMulitiply(a.getNum(), totalnum));
                }
            }
            //最高访问
            AccessVo maxobj = access.stream().max(Comparator.comparing(AccessVo::getNum)).get();
            maxnum = maxobj.getNum();
            ultype = maxobj.getUltype();
            String logtime = maxobj.getLogtime();
            if (N_Utils.isNotEmpty(logtime)) {
                map.put("logtime", logtime);
                access = access.stream().sorted(Comparator.comparing(AccessVo::getLogtime)).collect(Collectors.toList());
            }
        }
        map.put("maxnum", maxnum);
        map.put("ultype", ultype);
        map.put("access",access);
        map.put("totalnum",totalnum);
        return map;
    }

    //近一个月作业统计
    public List<Map> listPaperCommitMonth(RegionParam param) {
        if(N_Utils.isEmptyInteger(param.getYear())) {
            param.setYear(schoolMapper.getYearById(param.getSchoolid()));
        }
        List<SWorkVo> works = sAnalyzeMapper.listPaperCommitMonth(param);
        return getPaperGuide(works);
    }

    //近一个月预习统计
    public List<Map> listGuideCommitMonth(RegionParam param) {
        if(N_Utils.isEmptyInteger(param.getYear())) {
            param.setYear(schoolMapper.getYearById(param.getSchoolid()));
        }
        List<SWorkVo> works = sAnalyzeMapper.listGuideCommitMonth(param);
        return getPaperGuide(works);
    }

    private List<Map> getPaperGuide(List<SWorkVo> works) {
        List<Map> list = new ArrayList<>();
        if (works != null && works.size() > 0) {
            Map<Integer, List<SWorkVo>> grades = works.stream().collect(Collectors.groupingBy(w -> w.getGradeid()));
            for(Map.Entry gmap:grades.entrySet()) {
                Map map = new HashMap();
                List<SWorkVo> works2 = (List<SWorkVo>) gmap.getValue();
                //最高提交率
                SWorkVo maxobj = works2.stream().max(Comparator.comparing(SWorkVo::getNumrate)).get();
                //平均提交率
                double avgnumdouble = works2.stream().mapToDouble(SWorkVo::getNumrate).average().getAsDouble();
                works2 = works2.stream().sorted(Comparator.comparing(SWorkVo::getSubjectorder)).collect(Collectors.toList());

                map.put("avgrate", N_Utils.formatDouble(avgnumdouble,2));
                map.put("maxrate", maxobj.getNumrate());
                map.put("subjectname", maxobj.getSubjectname());
                map.put("gradeid", maxobj.getGradeid());
                map.put("works", works2);
                list.add(map);
            }
        }
        return list;
    }

    //近一个月课堂使用情况统计——使用次数
    public Map listRoomNumMonth(RegionParam param) {
        Map map = new HashMap();

        if(N_Utils.isEmptyInteger(param.getYear())) {
            param.setYear(schoolMapper.getYearById(param.getSchoolid()));
        }
        List<SWorkVo> rooms = sAnalyzeMapper.listRoomNumMonth(param);
        if (rooms != null && rooms.size() > 0) {
            //最大数量对象
            SWorkVo maxnum = rooms.stream().max(Comparator.comparing(SWorkVo::getNum)).get();
            //平均
            double avgnumdouble = rooms.stream().mapToInt(SWorkVo::getNum).average().getAsDouble();
            Integer avgnum = new Double(avgnumdouble).intValue();
            Integer totalnum = rooms.stream().collect(Collectors.summingInt(r->r.getNum()));

            map.put("totalnum",totalnum);
            map.put("avgnum", avgnum);
            map.put("maxnum", maxnum.getNum());
            map.put("gradeid", maxnum.getGradeid());
            map.put("classid", maxnum.getClassid());
            map.put("classname", maxnum.getClassname());
        }
        return map;
    }

    //近一个月课堂使用情况统计——课堂互动
    public List<Map> listRoomAskNumMonth(RegionParam param) {
        if(N_Utils.isEmptyInteger(param.getYear())) {
            param.setYear(schoolMapper.getYearById(param.getSchoolid()));
        }
        return sAnalyzeMapper.listRoomAskNumMonth(param);
    }
}
