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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.dto.obe.CourseRequirementMatrixDto;
import com.qmth.distributed.print.business.bean.dto.obe.MatrixRequirementDto;
import com.qmth.distributed.print.business.bean.dto.obe.MatrixSubRequirementDto;
import com.qmth.distributed.print.business.entity.ObeCourseRequirementMatrix;
import com.qmth.distributed.print.business.entity.ObeCultureProgram;
import com.qmth.distributed.print.business.entity.ObeCultureProgramRequirement;
import com.qmth.distributed.print.business.enums.CultureProgramRequirementEnum;
import com.qmth.distributed.print.business.mapper.ObeCourseRequirementMatrixMapper;
import com.qmth.distributed.print.business.mapper.ObeCultureProgramRequirementMapper;
import com.qmth.distributed.print.business.service.ObeCourseRequirementMatrixService;
import com.qmth.distributed.print.business.service.ObeCultureProgramRequirementService;
import com.qmth.distributed.print.business.service.ObeCultureProgramService;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;

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

/**
 * <p>
 * 培养方案毕业要求 服务实现类
 * </p>
 *
 * @author xf
 * @since 2024-06-05
 */
@Service
public class ObeCultureProgramRequirementServiceImpl extends ServiceImpl<ObeCultureProgramRequirementMapper, ObeCultureProgramRequirement> implements ObeCultureProgramRequirementService {

    private static final String NAME_PREFIX = "指标点";

    @Resource
    private ObeCultureProgramService obeCultureProgramService;
    @Resource
    private ObeCourseRequirementMatrixService obeCourseRequirementMatrixService;
    @Resource
    private ObeCourseRequirementMatrixMapper obeCourseRequirementMatrixMapper;

    @Override
    public List<ObeCultureProgramRequirement> listRequirement(Long cultureProgramId) {
        List<ObeCultureProgramRequirement> obeCultureProgramRequirementList = this.listByCultureProgramId(cultureProgramId);

        List<ObeCultureProgramRequirement> obeCultureProgramRequirements = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(obeCultureProgramRequirementList)) {
            Map<Long, ObeCultureProgramRequirement> obeCultureProgramRequirementMap = obeCultureProgramRequirementList.stream().filter(obeCultureProgramRequirement -> obeCultureProgramRequirement.getParentId() == null).collect(Collectors.toMap(ObeCultureProgramRequirement::getId, obeCultureProgramRequirement -> obeCultureProgramRequirement));
            for (ObeCultureProgramRequirement obeCultureProgramRequirement : obeCultureProgramRequirementList) {
                if (obeCultureProgramRequirement.getParentId() != null) {
                    obeCultureProgramRequirementMap.get(obeCultureProgramRequirement.getParentId()).getSubRequirementList().add(obeCultureProgramRequirement);
                }
            }
            obeCultureProgramRequirements = obeCultureProgramRequirementMap.values().stream().collect(Collectors.toList());
            obeCultureProgramRequirements.sort(Comparator.comparingInt(ObeCultureProgramRequirement::getSortNum));
        }
        return obeCultureProgramRequirements;
    }

    @Override
    public boolean saveRequirement(ObeCultureProgramRequirement obeCultureProgramRequirement) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        // 修改
        if (obeCultureProgramRequirement.getId() != null) {
            obeCultureProgramRequirement.updateInfo(sysUser.getId());
            return this.updateById(obeCultureProgramRequirement);
        }
        // 新增
//        else {
//            ObeCultureProgramRequirement obeCultureProgramRequirementParent = this.getById(obeCultureProgramRequirement.getParentId());
//            obeCultureProgramRequirement.setSortNum(this.getMaxSortNum(obeCultureProgramRequirement.getCultureProgramId(), obeCultureProgramRequirement.getParentId()) + 1);
//            obeCultureProgramRequirement.setName(concatRequirementName(obeCultureProgramRequirementParent.getSortNum(), obeCultureProgramRequirement.getSortNum()));
//            obeCultureProgramRequirement.insertInfo(sysUser.getId());
//            if (this.save(obeCultureProgramRequirement)) {
//                obeCourseRequirementMatrixService.updateMatrix(obeCultureProgramRequirement.getCultureProgramId(), Arrays.asList(obeCultureProgramRequirement), null);
//            }
//            return true;
//        }
        return true;
    }

    @Override
    public boolean addRequirementNode(ObeCultureProgramRequirement obeCultureProgramRequirement) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        ObeCultureProgramRequirement parentRequirement = this.getById(obeCultureProgramRequirement.getId());
        ObeCultureProgramRequirement cultureProgramRequirement = new ObeCultureProgramRequirement();
        cultureProgramRequirement.setCultureProgramId(obeCultureProgramRequirement.getCultureProgramId());
        cultureProgramRequirement.setSortNum(this.getMaxSortNum(cultureProgramRequirement.getCultureProgramId(), obeCultureProgramRequirement.getId()) + 1);
        cultureProgramRequirement.setName(concatRequirementName(parentRequirement.getSortNum(), cultureProgramRequirement.getSortNum()));
        cultureProgramRequirement.setParentId(obeCultureProgramRequirement.getId());
        cultureProgramRequirement.insertInfo(sysUser.getId());
        if (this.save(cultureProgramRequirement)) {
            parentRequirement.getSubRequirementList().add(cultureProgramRequirement);
            obeCourseRequirementMatrixService.updateMatrix(cultureProgramRequirement.getCultureProgramId(), Arrays.asList(parentRequirement), null);
        }
        return true;
    }

    @Override
    public int getMaxSortNum(Long cultureProgramId, Long parentId) {
        QueryWrapper<ObeCultureProgramRequirement> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ObeCultureProgramRequirement> lambda = queryWrapper.lambda();
        lambda.eq(ObeCultureProgramRequirement::getCultureProgramId, cultureProgramId);
        if (parentId != null) {
            lambda.eq(ObeCultureProgramRequirement::getParentId, parentId);
        }
        lambda.orderByDesc(ObeCultureProgramRequirement::getSortNum);
        lambda.last("limit 1");
        ObeCultureProgramRequirement requirement = this.getOne(queryWrapper);
        if (requirement == null) {
            return 0;
        } else {
            return requirement.getSortNum();
        }
    }

    @Transactional
    @Override
    public boolean removeRequirement(Long id) {
        ObeCultureProgramRequirement obeCultureProgramRequirement = this.getById(id);
        ObeCultureProgramRequirement obeCultureProgramRequirementParent = this.getById(obeCultureProgramRequirement.getParentId());
        obeCourseRequirementMatrixService.removeMatrixByCondition(new ObeCourseRequirementMatrix(null, null, null, id));
        if (this.removeById(id)) {
            List<ObeCultureProgramRequirement> obeCultureProgramRequirementList = this.listByCultureProgramIdAndParentId(obeCultureProgramRequirement.getCultureProgramId(), obeCultureProgramRequirement.getParentId());
            if (CollectionUtils.isEmpty(obeCultureProgramRequirementList)) {
                throw ExceptionResultEnum.ERROR.exception("当前数据为最后一个节点，无法删除");
            }
            for (int i = 0; i < obeCultureProgramRequirementList.size(); i++) {
                obeCultureProgramRequirementList.get(i).setSortNum(i + 1);
                obeCultureProgramRequirementList.get(i).setName(concatRequirementName(obeCultureProgramRequirementParent.getSortNum(), (i + 1)));
            }
            this.updateBatchById(obeCultureProgramRequirementList);
        }
        return true;
    }

    @Transactional
    @Override
    public void initRequirement(Long cultureProgramId) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        List<ObeCultureProgramRequirement> obeCultureProgramRequirementList = new ArrayList<>();
        for (CultureProgramRequirementEnum value : CultureProgramRequirementEnum.values()) {
            // 一级节点
            ObeCultureProgramRequirement obeCultureProgramRequirement = new ObeCultureProgramRequirement(cultureProgramId, value.name(), value.getName(), value.getContent(), null, value.ordinal() + 1);
            obeCultureProgramRequirement.insertInfo(sysUser.getId());
            obeCultureProgramRequirementList.add(obeCultureProgramRequirement);
            // 每个一级节点默认创建一个二级节点
            ObeCultureProgramRequirement obeSubCultureProgramRequirement = new ObeCultureProgramRequirement(cultureProgramId, null, concatRequirementName(obeCultureProgramRequirement.getSortNum(), 1), null, obeCultureProgramRequirement.getId(), 1);
            obeSubCultureProgramRequirement.insertInfo(sysUser.getId());
            obeCultureProgramRequirementList.add(obeSubCultureProgramRequirement);
        }

        this.saveBatch(obeCultureProgramRequirementList);
    }

    @Override
    public List<ObeCultureProgramRequirement> listByCultureProgramIdAndParentId(Long cultureProgramId, Long parentId) {
        QueryWrapper<ObeCultureProgramRequirement> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ObeCultureProgramRequirement> lambda = queryWrapper.lambda();
        lambda.eq(ObeCultureProgramRequirement::getCultureProgramId, cultureProgramId);
        if (parentId != null) {
            lambda.eq(ObeCultureProgramRequirement::getParentId, parentId);
        } else {
            lambda.isNull(ObeCultureProgramRequirement::getParentId);
        }
        lambda.orderByAsc(ObeCultureProgramRequirement::getSortNum);
        return this.list(queryWrapper);
    }

    @Transactional
    @Override
    public boolean saveRequirementExpect(ObeCultureProgramRequirement obeCultureProgramRequirement) {
        if (obeCultureProgramRequirement.getCultureProgramId() == null) {
            throw ExceptionResultEnum.ERROR.exception("培养方案ID有误");
        }
        UpdateWrapper<ObeCultureProgram> obeCultureProgramUpdateWrapper = new UpdateWrapper<>();
        obeCultureProgramUpdateWrapper.lambda().set(ObeCultureProgram::getExpectValue, obeCultureProgramRequirement.getExpectValue())
                .eq(ObeCultureProgram::getId, obeCultureProgramRequirement.getCultureProgramId());
        obeCultureProgramService.update(obeCultureProgramUpdateWrapper);

        UpdateWrapper<ObeCultureProgramRequirement> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(ObeCultureProgramRequirement::getExpectValue, obeCultureProgramRequirement.getExpectValue())
                .eq(ObeCultureProgramRequirement::getCultureProgramId, obeCultureProgramRequirement.getCultureProgramId())
                .isNull(ObeCultureProgramRequirement::getParentId);
        return this.update(updateWrapper);
    }

    @Override
    public void removeByCultureProgramId(Long id) {
        this.remove(new QueryWrapper<ObeCultureProgramRequirement>().lambda().eq(ObeCultureProgramRequirement::getCultureProgramId, id));
    }

    @Override
    public Map<Long, Long> copyByCultureProgramId(Long id, Long obeCultureProgramNewId) {
        List<ObeCultureProgramRequirement> obeCultureProgramRequirementList = this.listByCultureProgramId(id);
        // 原id与新id的映射关系
        Map<Long, Long> idMap = new HashMap<>();
        for (ObeCultureProgramRequirement obeCultureProgramRequirement : obeCultureProgramRequirementList) {
            Long newId = SystemConstant.getDbUuid();
            idMap.put(obeCultureProgramRequirement.getId(), newId);
            obeCultureProgramRequirement.setId(newId);
            obeCultureProgramRequirement.setCultureProgramId(obeCultureProgramNewId);
        }
        for (ObeCultureProgramRequirement obeCultureProgramRequirement : obeCultureProgramRequirementList) {
            obeCultureProgramRequirement.setParentId(idMap.get(obeCultureProgramRequirement.getParentId()));
        }
        if (CollectionUtils.isNotEmpty(obeCultureProgramRequirementList)) {
            this.saveBatch(obeCultureProgramRequirementList);
        }
        return idMap;
    }

    @Override
    public List<ObeCultureProgramRequirement> listByCultureProgramId(Long cultureProgramId) {
        QueryWrapper<ObeCultureProgramRequirement> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ObeCultureProgramRequirement::getCultureProgramId, cultureProgramId)
                .orderByAsc(ObeCultureProgramRequirement::getSortNum);
        return this.list(queryWrapper);
    }

    @Override
    public List<MatrixRequirementDto> listSubRequirement(Long cultureProgramId, Long courseId) {
        List<CourseRequirementMatrixDto> tpMatrixList = obeCourseRequirementMatrixMapper.listMatrix(cultureProgramId, courseId);

        List<CourseRequirementMatrixDto> filterCollect = tpMatrixList.stream().filter(tpMatrix -> tpMatrix.getScale() != null).collect(Collectors.toList());
        tpMatrixList = CollectionUtils.isNotEmpty(filterCollect) ? filterCollect : tpMatrixList;

        LinkedMultiValueMap<Long, CourseRequirementMatrixDto> requirementMap = new LinkedMultiValueMap<>();
        for (CourseRequirementMatrixDto tpMatrix : tpMatrixList) {
            requirementMap.add(tpMatrix.getObeRequirementId(), tpMatrix);
        }
        List<MatrixRequirementDto> matrixRequirementDtoList = new ArrayList<>();
        requirementMap.entrySet().stream().forEach(requirementEntry -> {
            ObeCultureProgramRequirement tpRequirement = this.getById(requirementEntry.getKey());
            MatrixRequirementDto matrixRequirementDto = new MatrixRequirementDto();
            matrixRequirementDto.setId(tpRequirement.getId());
            matrixRequirementDto.setName(tpRequirement.getName());
            matrixRequirementDto.setExpectValue(tpRequirement.getExpectValue());
            List<CourseRequirementMatrixDto> requirementList = requirementEntry.getValue();
            // 排序，解决字符串1和10排序问题
            if (requirementList.size() > 1) {
                requirementList.sort(Comparator.comparingInt(o -> o.getSubRequirementSortNum()));
            }

            List<MatrixSubRequirementDto> matrixSubRequirementDtoList = requirementList.stream().map(tpMatrix -> {
                MatrixSubRequirementDto matrixSubRequirementDto = new MatrixSubRequirementDto();
                matrixSubRequirementDto.setId(tpMatrix.getObeSubRequirementId());
                matrixSubRequirementDto.setName(concatRequirementName(tpMatrix.getRequirementSortNum(), tpMatrix.getSubRequirementSortNum()));
                matrixSubRequirementDto.setScale(tpMatrix.getScale());
                matrixSubRequirementDto.setContent(tpMatrix.getRequirementContent());
                return matrixSubRequirementDto;
            }).collect(Collectors.toList());
            matrixRequirementDto.setSubRequirements(matrixSubRequirementDtoList);
            matrixRequirementDtoList.add(matrixRequirementDto);
        });

        return matrixRequirementDtoList;
    }

    private String concatRequirementName(int requirementNum, int subRequirementNum) {
        return NAME_PREFIX + requirementNum + "-" + subRequirementNum;
    }
}
