package com.ruoyi.learn.domain;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.enums.SubjectType;
import com.ruoyi.enums.QuestionType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestPaperVO {
    @ApiModel("基本组卷请求")
    @Data
    public static class TestPaperBuildReq {
        @ApiModelProperty("是否定向")
        Boolean directType;

        // 所有
        @ApiModelProperty("组卷方式")
        String buildType;
        @ApiModelProperty("批次")
        Integer batchId;
        @ApiModelProperty("班级组")
        List<Long> classIds;
        @ApiModelProperty("班级")
        Long classId;

        // 全量智能+全量手动
        @ApiModelProperty("考生类型")
        String examType;
        @ApiModelProperty("科目")
        Long subjectId;

        // 全量智能
        @ApiModelProperty("院校")
        List<Long> knowledgeIds;
        List<TypeDef2> types;

        List<Long> studentIds;

        // 定向手动+全量手动
        @ApiModelProperty("名称")
        String name;
        @ApiModelProperty("试题列表")
        List<LearnPaperQuestion> questions;
        // 定向手动
        @ApiModelProperty("定向院校")
        Long universityId;
        @ApiModelProperty("定向专业组")
        String majorGroup;
        @ApiModelProperty("定向计划")
        Long majorPlanId;

        @ApiModelProperty("年度")
        Integer matchYear;

        @JsonIgnore
        Long teacherId;

        public TestPaperVO.PaperDef getPaperDef() {
            TestPaperVO.PaperDef paperDef = new TestPaperVO.PaperDef();
            paperDef.setFillExclude(false);
            paperDef.setKnowIds(knowledgeIds);
            Long total = 0L;
            if(CollectionUtils.isNotEmpty(types)) {
                List<TestPaperVO.TypeDef> typeDefList = Lists.newArrayList();
                for(TypeDef2 typeDef2 : types) {
                    total += null==typeDef2.getCount()?0:typeDef2.getCount();
                    TestPaperVO.TypeDef typeDef = new TestPaperVO.TypeDef();
                    BeanUtils.copyProperties(typeDef2, typeDef);
                    typeDef.setType(typeDef.getTitle());
                    typeDef.setScore(typeDef2.getScore().intValue());
                    if(null == typeDef.getScore()) {
                        typeDef.setScore(1);
                    }
                    typeDefList.add(typeDef);
                }
                paperDef.setTypes(typeDefList);
            }
            paperDef.setTotal(total);
            return paperDef;
        }

        public Map<String, Object> toMap() {
            Map<String, Object> map = Maps.newHashMap();
            map.put("directed", directType);
            map.put("subjectId", subjectId);
            map.put("buildType", buildType);
            map.put("batchId", batchId);
            map.put("classIds", classIds);
            map.put("examType", examType);
            map.put("universityId", universityId);
            if(null == majorPlanId) {
                map.put("majorGroup", majorGroup);
            }
            map.put("majorPlanId", majorPlanId);
            map.put("teacherId", teacherId);
            map.put("classId", classId);
            map.put("year", Calendar.getInstance().get(Calendar.YEAR));
            return map;
        }
    }

    @Data
    public static class PaperDef {
        Long total;
        List<Long> knowIds;
        Boolean fillExclude; // 不足时是否填充排除的
        List<TestPaperVO.TypeDef> types;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class TypeDef {
        String title;
        String type;
        Integer count;
        Integer score;
    }


    @Data
    @NoArgsConstructor
    public static class PaperDef2 {
        Double score;
        Integer total;
        Boolean fillExclude;
        List<TypeDef2> types;
        List<KnowledgeTypeDef2> knowTypes;

        public PaperDef2(String conditions) {
            types = Lists.newArrayList();
            knowTypes = JSONArray.parseArray(conditions, KnowledgeTypeDef2.class);
            this.total = 0;
            this.score = 0.0;

            Map<String, TypeDef2> typeMap = Maps.newHashMap();
            for(KnowledgeTypeDef2 kt : knowTypes) {
                kt.setCount(0);
                kt.setScore(0.0);
                for(TypeDef2 kd : kt.getTypes()) {
                    TypeDef2 cType = typeMap.get(kd.getType().name());

                    Double kdScore = kd.getScore() * kd.getCount();
                    this.total += kd.getCount();
                    this.score += kdScore;
                    if(null == cType) {
                        cType = new TypeDef2();
                        BeanUtils.copyProperties(kd, cType);
                        cType.setScore(kdScore);
                        types.add(cType);
                        typeMap.put(kd.getType().name(), cType);
                    } else {
                        cType.setScore(cType.getScore() + kdScore);
                        cType.setCount(cType.getCount() + kd.getCount());
                    }
                    kt.setScore(kt.getScore() + kdScore);
                    kt.setCount(kt.getCount() + kd.getCount());
                }
            }
        }
        public PaperDef2(String knowledges, String json) {
            JSONArray root = JSONArray.parseArray(json);
            this.total = 0;
            this.score = 0.0;
            this.types = Lists.newArrayList();
            this.knowTypes = Lists.newArrayList();
            Map<String, TypeDef2> typeMap = Maps.newHashMap();  // 合并题型
            root.forEach(item -> {
                JSONObject obj = (JSONObject) item;

                KnowledgeTypeDef2 ktd = new KnowledgeTypeDef2();
                ktd.setScore(obj.getDouble("score"));
                ktd.setCount(0);
                JSONArray knowledgeList = obj.getJSONArray("knowledges");
                if (null != knowledgeList && knowledgeList.size() > 0) {
                    ktd.setKnowledges(knowledgeList.stream().map(t -> Long.parseLong(t.toString())).collect(Collectors.toList()));
                } else if(StringUtils.isBlank(knowledges)) {
                    return;
                } else {
                    ktd.setKnowledges(Stream.of(StringUtils.trimToEmpty(knowledges).split(",")).map(Long::parseLong).collect(Collectors.toList()));
                }
                JSONObject typeObj = obj.getJSONObject("types");
                List<TypeDef2> subTypes = Lists.newArrayList();
                for(QuestionType qt : QuestionType.values()) {
                    String val = typeObj.getString(qt.name().toLowerCase());
                    String[] datas;
                    if(StringUtils.isBlank(val) || "0".equals(val) || (datas = val.split("/")).length < 2) {
                        continue;
                    }
                    TypeDef2 typeDef = new TypeDef2();
                    typeDef.setType(qt);
                    typeDef.setTitle(qt.getTitle());
                    typeDef.setCount(Integer.parseInt(datas[0]));
                    typeDef.setScore(Double.parseDouble(datas[1]));

                    TypeDef2 cType = typeMap.get(qt.name());
                    if(null == cType) {
                        cType = new TypeDef2();
                        BeanUtils.copyProperties(typeDef, cType);
                        cType.setScore(typeDef.getScore() * typeDef.getCount());
                        types.add(cType);
                        typeMap.put(qt.name(), cType);
                    } else {
                        cType.setScore(cType.getScore() + typeDef.getScore() * typeDef.getCount());
                        cType.setCount(cType.getCount() + typeDef.getCount());
                    }
                    this.total += typeDef.getCount();
                    ktd.setCount(ktd.getCount() + typeDef.getCount());
                    subTypes.add(typeDef);
                }
                if(CollectionUtils.isNotEmpty(subTypes)) {
                    ktd.setTypes(subTypes);
                    knowTypes.add(ktd);
                }
                this.score += ktd.getScore();
            });
            types.forEach(t -> t.setScore(t.getScore() / t.getCount()));
        }
    }


    @Data
    public static class KnowledgeTypeDef2 {
        Integer count;
        Double score;
        List<Long> knowledges;
        Integer subType; // 是否子题 1是 0不是
        List<TypeDef2> types = Lists.newArrayList();
    }

    @Data
    public static class TypeDef2 {
        String title;
        QuestionType type;
        Integer count;
        Double score;
    }

}
