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.examRule.CodeName;
import com.qmth.distributed.print.business.bean.examRule.CodeNameEnableDisabled;
import com.qmth.distributed.print.business.bean.examRule.FieldsDto;
import com.qmth.distributed.print.business.entity.BasicExamRule;
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.entity.SysUser;
import com.qmth.teachcloud.common.enums.EnumResult;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
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;

    @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);

        List<EnumResult> enumResultList = RequiredFieldsEnum.listTypes();
        BasicExamRule basicExamRule = this.getOne(queryWrapper);
        if (basicExamRule == null) {
            basicExamRule = new BasicExamRule();
            basicExamRule.setSchoolId(schoolId);
            basicExamRule.setOrgId(sysUser.getOrgId());
            basicExamRule.setRequiredFields(JSON.toJSONString(enumResultList));
            String emptyObject = JSON.toJSONString(new ArrayList<>());
            basicExamRule.setExtendFields(emptyObject);
            basicExamRule.setSignScope(emptyObject);
            basicExamRule.setPackageScope(emptyObject);
        } else {
            List<EnumResult> requiredFields = JSON.parseArray(basicExamRule.getRequiredFields(), EnumResult.class);
            for (EnumResult enumResult : enumResultList) {
                Optional<EnumResult> resultOptional = requiredFields.stream().filter(t -> enumResult.getCode().equals(t.getCode())).findFirst();
                if (resultOptional.isPresent()) {
                    enumResult.setEnable(enumResult.getEnable() ? enumResult.getEnable() : resultOptional.get().getEnable());
                }
//                else {
//                    enumResult.setEnable(false);
//                }
            }
            basicExamRule.setRequiredFields(JSON.toJSONString(enumResultList));

            List<EnumResult> extendFields = JSON.parseArray(basicExamRule.getExtendFields(), EnumResult.class);
            if (!CollectionUtils.isEmpty(extendFields)) {
                requiredFields.addAll(extendFields);
            }
            // 签到表范围
            if (StringUtils.isNotBlank(basicExamRule.getSignScope())) {
                JSONObject signJson = JSON.parseObject(basicExamRule.getSignScope());
                List<CodeName> signScopeBasicFields = JSON.parseArray(signJson.getString("basic"), CodeName.class);
                List<CodeName> newSignScopeBasicFields = new ArrayList<>();
                for (CodeName enumResult : signScopeBasicFields) {
                    Optional<EnumResult> resultOptional = requiredFields.stream().filter(t -> enumResult.getCode().equals(t.getCode())).findFirst();
                    if (resultOptional.isPresent() && resultOptional.get().getEnable()) {
                        enumResult.setName(resultOptional.get().getName());
                        newSignScopeBasicFields.add(enumResult);
                    }
                }
                signJson.put("basic", newSignScopeBasicFields);

                List<CodeName> signScopeTableFields = JSON.parseArray(signJson.getString("table"), CodeName.class);
                List<CodeName> newSignScopeTableFields = new ArrayList<>();
                for (CodeName enumResult : signScopeTableFields) {
                    Optional<EnumResult> resultOptional = requiredFields.stream().filter(t -> enumResult.getCode().equals(t.getCode())).findFirst();
                    if (resultOptional.isPresent() && resultOptional.get().getEnable()) {
                        enumResult.setName(resultOptional.get().getName());
                        newSignScopeTableFields.add(enumResult);
                    }
                }
                signJson.put("table", newSignScopeTableFields);
                basicExamRule.setSignScope(JSON.toJSONString(signJson));
            }

            // 卷袋贴范围
            if (StringUtils.isNotBlank(basicExamRule.getPackageScope())) {
                JSONObject packageJson = JSON.parseObject(basicExamRule.getPackageScope());
                List<CodeName> packageScopeFields = JSON.parseArray(packageJson.getString("basic"), CodeName.class);
                List<CodeName> newPackageScopeFields = new ArrayList<>();
                for (CodeName enumResult : packageScopeFields) {
                    Optional<EnumResult> resultOptional = requiredFields.stream().filter(t -> enumResult.getCode().equals(t.getCode())).findFirst();
                    if (resultOptional.isPresent() && resultOptional.get().getEnable()) {
                        enumResult.setName(resultOptional.get().getName());
                        newPackageScopeFields.add(enumResult);
                    }
                }
                packageJson.put("basic", newPackageScopeFields);
                basicExamRule.setPackageScope(JSON.toJSONString(packageJson));
            }

        }
        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);

        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() + "]在基础字段中已使用");
                }
            }
        }

        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        // 新增
        if (examRule.getId() == null) {
            examRule.insertInfo(sysUser.getId());
            examRule.setOrgId(sysUser.getOrgId());
            this.save(examRule);
        }
        // 修改
        else {
            examRule.updateInfo(sysUser.getId());
            this.updateById(examRule);
        }
        return examRule.getId();
    }
}
