package com.qmth.distributed.print.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.dto.FieldsDto;
import com.qmth.distributed.print.business.entity.BasicExamRule;
import com.qmth.distributed.print.business.entity.ExamPrintPlan;
import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
import com.qmth.distributed.print.business.enums.RequiredFieldsEnum;
import com.qmth.distributed.print.business.mapper.BasicExamRuleMapper;
import com.qmth.distributed.print.business.service.BasicExamRuleService;
import com.qmth.distributed.print.business.service.ExamPrintPlanService;
import com.qmth.teachcloud.common.bean.dto.DataPermissionRule;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.EnumResult;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.BasicRoleDataPermissionService;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 考务规则 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class BasicExamRuleServiceImpl extends ServiceImpl<BasicExamRuleMapper, BasicExamRule> implements BasicExamRuleService {

    @Resource
    private ExamPrintPlanService examPrintPlanService;
    @Resource
    private BasicRoleDataPermissionService basicRoleDataPermissionService;

    @Override
    public BasicExamRule getBySchoolId() {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());

        QueryWrapper<BasicExamRule> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicExamRule::getSchoolId, schoolId);

        BasicExamRule basicExamRule = this.getOne(queryWrapper);
        if (basicExamRule == null) {
            List<EnumResult> enumResultList = RequiredFieldsEnum.listTypes();
            List<JSONObject> requiredObjects = enumResultList.stream().map(m -> {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", m.getCode());
                jsonObject.put("name", m.getDesc());
                jsonObject.put("enable", true);
                return jsonObject;
            }).collect(Collectors.toList());

            basicExamRule = new BasicExamRule();
            basicExamRule.setSchoolId(schoolId);
            basicExamRule.setOrgId(sysUser.getOrgId());
            basicExamRule.setRequiredFields(JSON.toJSONString(requiredObjects));
            String emptyObject = JSON.toJSONString(new ArrayList<>());
            basicExamRule.setExtendFields(emptyObject);
            basicExamRule.setSignScope(emptyObject);
            basicExamRule.setPackageScope(emptyObject);
        }
        return basicExamRule;
    }

    @Override
    public BasicExamRule getBySchoolId(Long schoolId) {
        QueryWrapper<BasicExamRule> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicExamRule::getSchoolId, schoolId);
        return this.getOne(queryWrapper);
    }

    @Override
    public Long saveExamRule(BasicExamRule examRule) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        examRule.setSchoolId(schoolId);
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        List<FieldsDto> extendFieldList = JSONObject.parseArray(examRule.getExtendFields(), FieldsDto.class);
        if (!CollectionUtils.isEmpty(extendFieldList)) {
            // 校验扩展字段变量名是否重复
            Map<String, List<FieldsDto>> byCodeCollect = extendFieldList.stream().collect(Collectors.groupingBy(FieldsDto::getCode));
            for (Map.Entry<String, List<FieldsDto>> entry : byCodeCollect.entrySet()) {
                if (entry.getValue().size() > 1) {
                    throw ExceptionResultEnum.ERROR.exception("扩展字段中字段变量名[" + entry.getKey() + "]有" + entry.getValue().size() + "个重复");
                }
            }
            // 校验扩展字段名称是否重复
            Map<String, List<FieldsDto>> byNameCollect = extendFieldList.stream().collect(Collectors.groupingBy(FieldsDto::getName));
            for (Map.Entry<String, List<FieldsDto>> entry : byNameCollect.entrySet()) {
                if (entry.getValue().size() > 1) {
                    throw ExceptionResultEnum.ERROR.exception("扩展字段中字段名称[" + entry.getKey() + "]有" + entry.getValue().size() + "个重复");
                }
            }

            // 校验扩展字段变量名是否与必选字段重复
            List<FieldsDto> requiredFieldList = JSONObject.parseArray(examRule.getRequiredFields(), FieldsDto.class);
            for (FieldsDto fieldsDto : extendFieldList) {
                long count = requiredFieldList.stream().filter(t -> t.getCode().equals(fieldsDto.getCode())).count();
                if (count > 0) {
                    throw ExceptionResultEnum.ERROR.exception("扩展字段中字段变量名[" + fieldsDto.getCode() + "]在必选字段中已存在");
                }
            }

            // 校验扩展字段名称是否与必选字段重复
            for (FieldsDto fieldsDto : extendFieldList) {
                long count = requiredFieldList.stream().filter(t -> t.getName().equals(fieldsDto.getName())).count();
                if (count > 0) {
                    throw ExceptionResultEnum.ERROR.exception("扩展字段中字段名称[" + fieldsDto.getName() + "]在必选字段中已存在");
                }
            }
        }

        // 新增
        if (examRule.getId() == null) {
            examRule.insertInfo(sysUser.getId());
            examRule.setOrgId(sysUser.getOrgId());
            this.save(examRule);
        }
        // 修改
        else {
            // 查询未结束的印刷计划
            QueryWrapper<ExamPrintPlan> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ExamPrintPlan::getSchoolId, schoolId).ne(ExamPrintPlan::getStatus, PrintPlanStatusEnum.END);
            List<ExamPrintPlan> examPrintPlanList = examPrintPlanService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(examPrintPlanList)) {
                BasicExamRule basicExamRule = this.getById(examRule.getId());
                // 匹配扩展字段是否有变动
                String oldExtends = basicExamRule.getExtendFields();
                String newExtends = examRule.getExtendFields();
                List<FieldsDto> oldFieldList = JSONObject.parseArray(oldExtends, FieldsDto.class);
                List<FieldsDto> newFieldList = JSONObject.parseArray(newExtends, FieldsDto.class);
                oldFieldList.sort(Comparator.comparing(FieldsDto::getCode));
                newFieldList.sort(Comparator.comparing(FieldsDto::getCode));

                // md5加密
                String md5OldExtends = DigestUtils.md5DigestAsHex(JSONObject.toJSONBytes(oldFieldList));
                String newOldExtends = DigestUtils.md5DigestAsHex(JSONObject.toJSONBytes(newFieldList));
                if (!md5OldExtends.equals(newOldExtends)) {
                    throw ExceptionResultEnum.ERROR.exception("有未结束的印刷计划，不能修改扩展字段");
                }
            }
            examRule.updateInfo(sysUser.getId());
            this.updateById(examRule);
        }
        return examRule.getId();
    }
}
