package com.app.service.report;

import com.app.constant.SchoolConstant;
import com.app.dto.report.*;
import com.app.entity.BaseEntity;
import com.app.entity.basics.School;
import com.app.entity.order.OpenCourseOrderItem;
import com.app.mapper.basics.SchoolMapper;
import com.app.mapper.guardian.GuardianChildMapper;
import com.app.mapper.order.OpenCourseOrderItemMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ReportService {

    @Autowired
    private SchoolMapper schoolMapper;

    @Autowired
    private OpenCourseOrderItemMapper openCourseOrderItemMapper;

    @Autowired
    private GuardianChildMapper guardianChildMapper;

    private int roundTen(double db) {
        int roundedInt = (int) Math.round(db);

        if (roundedInt % 10 < 5) {
            return (roundedInt / 10) * 10;
        }

        return (roundedInt / 10) * 10 + 10;
    }

    public ReportAllDto reportAll(SearchReportDto searchReportDto) {
        List<Double> money = new ArrayList<>();
        List<Integer> num = new ArrayList<>();
        List<Integer> peopleNum = new ArrayList<>();

        List<School> schools = schoolMapper.getSchoolList(searchReportDto);
        List<String> schoolNameList = new ArrayList<>();
        for (School school : schools) {
            schoolNameList.add(school.getName());
            int peopleNumber = 0;
            double moneyBySchool = 0;

            LambdaQueryWrapper<OpenCourseOrderItem> wrapper = new QueryWrapper().lambda();
            if (!StringUtils.isEmpty(searchReportDto.getSchoolYear())) {
                wrapper.eq(OpenCourseOrderItem::getSchoolYear, searchReportDto.getSchoolYear());
            }
            if (!StringUtils.isEmpty(searchReportDto.getSemester())) {
                wrapper.eq(OpenCourseOrderItem::getSemester, searchReportDto.getSemester());
            }
            wrapper.eq(OpenCourseOrderItem::getSchoolId, school.getId());
            wrapper.eq(BaseEntity::getIsDel, Boolean.FALSE);
            List<OpenCourseOrderItem> allOpenCourseOrderItem = openCourseOrderItemMapper.selectList(wrapper);

            List<ListDto> _peopleNum = guardianChildMapper.findPeopleNum(school.getId());
            int peopleSum = 0;
            for (ListDto listDto : _peopleNum) {
                peopleSum += listDto.getCount();
            }
            peopleNum.add(peopleSum);

            if (!ObjectUtils.isEmpty(allOpenCourseOrderItem)) {
                double sum = 0;
                for (OpenCourseOrderItem allOpenCourseOrder :
                        allOpenCourseOrderItem) {
                    peopleNumber++;
                    sum += allOpenCourseOrder.getPrice();
                }
                moneyBySchool += sum;

            }
            money.add(moneyBySchool);
            num.add(peopleNumber);
        }

        ReportAllDto reportAllDto = new ReportAllDto();
        reportAllDto.setPeopleNum(peopleNum);
        reportAllDto.setMoney(money.toArray(new Double[money.size()]));
        reportAllDto.setNum(num.toArray(new Integer[num.size()]));
        reportAllDto.setSchoolList(schoolNameList.toArray(new String[schoolNameList.size()]));

        List<Integer> listMeney = getlist(money, null);
        reportAllDto.setMoneyMax(listMeney.get(0));
        reportAllDto.setMoneyInterval(listMeney.get(1));

        List<Integer> listTimes = getlist(null, num);
        reportAllDto.setTimesMax(listTimes.get(0));
        reportAllDto.setTimesInterval(listTimes.get(1));

        return reportAllDto;
    }

    public List<Integer> getlist(List<Double> listDouble, List<Integer> listInt) {
        List<Integer> returnListDefault = new ArrayList<>();
        returnListDefault.add(10);
        returnListDefault.add(1);
        double maxTimes = 0.0;
        try {
            if (!ObjectUtils.isEmpty(listDouble)) {
                Collections.sort(listDouble);
                //2.拿出来
                maxTimes = listDouble.get(listDouble.size() - 1);
            } else {

                Collections.sort(listInt);
                //2.拿出来

                maxTimes = listInt.get(listInt.size() - 1);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            return returnListDefault;
        }

        //3.拿8份
        double _maxTimes = maxTimes / 0.6;
        //3.拿10份之1
        String tempTimes = String.valueOf(Math.round(_maxTimes) / 10);
        //拿长度
        int lengthTimes = tempTimes.length();
        int roundTenTimes = 0;
        try {
            roundTenTimes = roundTen(Integer.valueOf(tempTimes.substring(0, 2)));
        } catch (StringIndexOutOfBoundsException e) {
            roundTenTimes = 10;
        }

        List list1 = new ArrayList();
        double _tempTimes = roundTenTimes * (Math.pow(10, lengthTimes - 2));
        list1.add(new Double(_tempTimes * 10).intValue());
        list1.add(new Double(_tempTimes).intValue());
        return list1;
    }

    public ReportSchoolDto findReportByClass(SearchReportDto searchReportDto) {
        List<Integer> allNum = new ArrayList<>();
        List<Integer> allNumNum = new ArrayList<>();
        ReportSchoolDto reportSchoolDto = new ReportSchoolDto();
        List<ReportClassSeriesDto> reportSeriesDtoList = new ArrayList<>();
        List<String> classList = openCourseOrderItemMapper.findClassName();
        for (int i = classList.size() - 1; i >= 0; i--) {
            String className = classList.get(i);
            Integer classNum = openCourseOrderItemMapper.exportClassName(className, searchReportDto.getSchoolId());
            if (classNum == 0) {
                classList.remove(i);
            } else {
                break;
            }
        }

        List<ListDto> _peopleNum = guardianChildMapper.findPeopleNum(searchReportDto.getSchoolId());

        Map<String, List<String>> classListMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(classList)) {
            classListMap = classList.stream().collect(Collectors.groupingBy(a -> a));
        }
        for (Map.Entry<String, List<String>> entry : classListMap.entrySet()) {
            List<String> mapValue = entry.getValue();
            mapValue.clear();
        }
        List<String> gradeList = new ArrayList<>();
        School mSchool = schoolMapper.selectById(searchReportDto.getSchoolId());
        reportSchoolDto.setName(mSchool.getName());
        if (mSchool.getGradeYear().equals("1")) {
            for (String text : SchoolConstant.getPrimarySchool()) {
                gradeList.add(text);
            }
        }
        if (mSchool.getGradeYear().equals("2")) {
            for (String text : SchoolConstant.getMiddleSchool()) {
                gradeList.add(text);
            }
        }
        if (mSchool.getGradeYear().equals("3")) {
            for (String text : SchoolConstant.getHighSchool()) {
                gradeList.add(text);
            }
        }

        Map<String, List<String>> classListMapNum = new HashMap<>();

        if (!CollectionUtils.isEmpty(classList)) {
            classListMapNum = classList.stream().collect(Collectors.groupingBy(a -> a));
        }
        for (Map.Entry<String, List<String>> entry : classListMapNum.entrySet()) {
            List<String> mapValue = entry.getValue();
            mapValue.clear();
        }

        for (String grade : gradeList) {
            for (String className : classList) {
                Integer num = openCourseOrderItemMapper.selectClassEcharts(searchReportDto.getSchoolYear(), searchReportDto.getSemester(), className, searchReportDto.getSchoolId(), grade);

                List<String> _listNum = classListMapNum.get(className);
                List<String> _list = classListMap.get(className);

                String temp = "0";
                for (ListDto listDto : _peopleNum) {
                    if (listDto.getClassName().equals(className) && listDto.getGradeName().equals(grade)) {
                        temp = listDto.getCount().toString();
                        break;
                    }
                }
                _listNum.add(temp);
                classListMapNum.put(className, _listNum);
                _list.add(num.toString());
                classListMap.put(className, _list);
            }
        }

        for (Map.Entry<String, List<String>> entry : classListMap.entrySet()) {
            String mapKey = entry.getKey();
            List<String> mapValue = entry.getValue();
            ReportClassSeriesDto reportSeriesDto = new ReportClassSeriesDto();
            reportSeriesDto.setName(mapKey);

            List<Integer> list = mapValue.stream().map(Integer::parseInt).collect(Collectors.toList());
            //List<Integer>求和
            reportSeriesDto.setData(list);
            reportSeriesDtoList.add(reportSeriesDto);
        }

        for (Map.Entry<String, List<String>> entry : classListMapNum.entrySet()) {
            String mapKey = entry.getKey();
            List<String> mapValue = entry.getValue();
            ReportClassSeriesDto reportSeriesDto = new ReportClassSeriesDto();
            reportSeriesDto.setName(mapKey);
            reportSeriesDto.setStack("人数");
            List<Integer> list = mapValue.stream().map(Integer::parseInt).collect(Collectors.toList());
            //List<Integer>求和
            reportSeriesDto.setData(list);
            reportSeriesDtoList.add(reportSeriesDto);
        }

        for (int i = 0; i < gradeList.size(); i++) {
            int sum = 0;
            for (Map.Entry<String, List<String>> entry : classListMap.entrySet()) {
                List<String> mapValue = entry.getValue();
                List<Integer> list = mapValue.stream().map(Integer::parseInt).collect(Collectors.toList());
                sum += list.get(i);
            }
            allNum.add(sum);
        }
        ReportClassSeriesDto lineDto = new ReportClassSeriesDto();
        lineDto.setName("人总数");
        lineDto.setType("line");
        lineDto.setStack("");
        lineDto.setData(allNum);


        for (int i = 0; i < gradeList.size(); i++) {
            int sum = 0;
            for (Map.Entry<String, List<String>> entry : classListMapNum.entrySet()) {
                List<String> mapValue = entry.getValue();
                List<Integer> list = mapValue.stream().map(Integer::parseInt).collect(Collectors.toList());
                sum += list.get(i);
            }
            allNumNum.add(sum);
        }
        lineDto = new ReportClassSeriesDto();
        lineDto.setName("人数总数");
        lineDto.setType("line");
        lineDto.setStack("");
        lineDto.setData(allNumNum);
        reportSeriesDtoList.add(lineDto);

        List<Integer> intbackupNum = new ArrayList<>();

        for (int i = 0; i < gradeList.size(); i++) {
            int sum = 0;
            for (Map.Entry<String, List<String>> entry : classListMap.entrySet()) {
                List<String> mapValue = entry.getValue();
                List<Integer> list = mapValue.stream().map(Integer::parseInt).collect(Collectors.toList());
                sum += list.get(i);
            }
            intbackupNum.add(sum);
        }
        lineDto = new ReportClassSeriesDto();
        lineDto.setName("人次总数");
        lineDto.setType("line");
        lineDto.setStack("");
        lineDto.setData(intbackupNum);
        reportSeriesDtoList.add(lineDto);

        reportSchoolDto.setReportSeriesDtos(reportSeriesDtoList);
        reportSchoolDto.setAllNum(allNum);
        reportSchoolDto.setClassList(classList.toArray(new String[classList.size()]));
        reportSchoolDto.setGradeList(gradeList.toArray(new String[gradeList.size()]));

        List<Integer> listTimes = getlist(null, allNum);
        reportSchoolDto.setTimesMax(listTimes.get(0));
        reportSchoolDto.setTimesInterval(listTimes.get(1));
        return reportSchoolDto;
    }

    public ReportHobbySeriesDto findReportByHobby(SearchReportDto searchReportDto) {
        ReportHobbySeriesDto _reportHobbySeriesDto = new ReportHobbySeriesDto();
        List<Integer> hobbyNum = new ArrayList<>();
        List<String> nameList = openCourseOrderItemMapper.findName(searchReportDto.getSchoolId());
        for (String name : nameList) {
            Integer num = openCourseOrderItemMapper.selectHobbyEcharts(searchReportDto.getSchoolYear(), searchReportDto.getSemester(), searchReportDto.getSchoolId(), name);
            hobbyNum.add(num);
        }
        _reportHobbySeriesDto.setType("bar");
        _reportHobbySeriesDto.setData(hobbyNum);
        _reportHobbySeriesDto.setNameList(nameList);

        List<Integer> listTimes = getlist(null, hobbyNum);
        _reportHobbySeriesDto.setTimesMax(listTimes.get(0));
        _reportHobbySeriesDto.setTimesInterval(listTimes.get(1));
        return _reportHobbySeriesDto;
    }

}
