package com.xinyilu.system.service.itemCategory.impl;

import com.xinyilu.common.constant.Constants;
import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.exception.ServiceException;
import com.xinyilu.common.utils.DateUtils;
import com.xinyilu.common.utils.codes.GenerateSystemCodeUtil;
import com.xinyilu.system.domain.dto.TestItemCategoryDTO;
import com.xinyilu.system.domain.itemCategory.TestItemCategory;
import com.xinyilu.system.domain.testLevel.TestItemLevel;
import com.xinyilu.system.domain.vo.TestItemCategoryVO;
import com.xinyilu.system.mapper.itemCategory.TestItemCategoryMapper;
import com.xinyilu.system.mapper.testItemLevel.TestItemLevelMapper;
import com.xinyilu.system.service.itemCategory.ITestItemCategoryService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 测试项目分类Service业务层处理
 *
 * @author jihan
 * @date 2022-08-01
 */
@Service
public class TestItemCategoryServiceImpl implements ITestItemCategoryService {
    @Resource
    private TestItemCategoryMapper testItemCategoryMapper;
    @Resource
    private TestItemLevelMapper testItemLevelMapper;
    @Resource
    private GenerateSystemCodeUtil generateSystemCodeUtil;

    /**
     * 查询测试项目分类
     *
     * @param id 测试项目分类主键
     * @return 测试项目分类
     */
    @Override
    public TestItemCategoryVO selectTestItemCategoryById(Long id) {
        TestItemCategoryVO testItemCategoryVO = testItemCategoryMapper.selectTestItemCategoryById(id);
        if (Objects.isNull(testItemCategoryVO)) {
            return null;
        }
        //查询测试项目分类级别信息
        List<TestItemLevel> testItemLevelList = testItemLevelMapper.getTestItemLevel(id);
        if (CollectionUtils.isNotEmpty(testItemLevelList)) {
            testItemCategoryVO.setTestItemLevelList(testItemLevelList);
        }
        return testItemCategoryVO;
    }

    /**
     * 查询测试项目分类列表
     *
     * @param testItemCategory 测试项目分类
     * @return 测试项目分类
     */
    @Override
    public List<TestItemCategory> selectTestItemCategoryList(TestItemCategory testItemCategory) {
        return testItemCategoryMapper.selectTestItemCategoryList(testItemCategory);
    }

    /**
     * 新增测试项目分类
     *
     * @param testItemCategory 测试项目分类
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertTestItemCategory(TestItemCategoryDTO testItemCategory) {
        //根据分类名称去查询项目分类数据信息
        int testItemCategoryIds = testItemCategoryMapper.getTestItemCategoryIds(testItemCategory.getParentId(), testItemCategory.getCategoryName());
        if (testItemCategoryIds > 0) {
            return AjaxResult.error("分类名称已经存在，请重新输入！");
        }
        //新增测试分类表信息
        testItemCategory.setDelFlag(0);
        testItemCategory.setCreateTime(DateUtils.getNowDate());
        //父节点id
        int rootCategoryCount = testItemCategoryMapper.getRootCategoryInfo();
        if (rootCategoryCount > 0) {
            //当前分类信息不是根节点
            testItemCategory.setParentId(Objects.isNull(testItemCategory.getParentId()) ? 0L : testItemCategory.getParentId());
        } else {
            //当前分类信息是根节点
            testItemCategory.setParentId(0L);
        }
        // 随机生成分类编号
        testItemCategory.setCategoryCode(Constants.FL_PREFIX + generateSystemCodeUtil.generateSystemCode(Constants.PC_PREFIX));
        int insertCategoryCount = testItemCategoryMapper.insertTestItemCategory(testItemCategory);
        if (insertCategoryCount <= 0) {
            throw new ServiceException("新增项目分类信息失败");
        }
        if (CollectionUtils.isEmpty(testItemCategory.getTestItemLevelList())) {
            return AjaxResult.success();
        }
        //新增测试项目分类级别信息
        this.insertCategoryLevelInfo(testItemCategory.getTestItemLevelList(), testItemCategory.getId(), testItemCategory.getCreateBy());
        return AjaxResult.success();
    }

    /**
     * 修改测试项目分类
     *
     * @param testItemCategory 测试项目分类
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateTestItemCategory(TestItemCategoryDTO testItemCategory) {
        //查询原有测试项目分类信息
        TestItemCategoryVO testItemCategoryVO = testItemCategoryMapper.selectTestItemCategoryById(testItemCategory.getId());
        if (Objects.isNull(testItemCategoryVO)) {
            return AjaxResult.error("测试项目分类信息不存在");
        }
        if (!testItemCategory.getCategoryName().equals(testItemCategoryVO.getCategoryName())) {
            //根据分类名称  去查询项目分类数据信息
            int testItemCategoryIds = testItemCategoryMapper.getTestItemCategoryIds(testItemCategory.getParentId(), testItemCategory.getCategoryName());
            if (testItemCategoryIds > 0) {
                return AjaxResult.error("分类名称已经存在，请重新输入！");
            }
        }
        //修改测试项目主表信息
        testItemCategory.setUpdateTime(DateUtils.getNowDate());
        testItemCategory.setDelFlag(0);
        int updateCategoryCount = testItemCategoryMapper.updateTestItemCategory(testItemCategory);
        if (updateCategoryCount <= 0) {
            throw new ServiceException("修改测试项目分类信息失败");
        }
        //删除测试项目分类成绩级别信息
        int levelCategoryCount = testItemLevelMapper.getTestItemLevelByCategoryId(testItemCategory.getId());
        if (levelCategoryCount > 0) {
            //当前项目分类有级别信息，删除原有级别信息
            int deleteCategoryCount = testItemLevelMapper.deleteTestItemLevelByCategory(testItemCategory.getId());
            if (deleteCategoryCount <= 0) {
                throw new ServiceException("删除项目分类成绩级别信息失败");
            }
        }
        //新增测试项目分类级别信息
        this.insertCategoryLevelInfo(testItemCategory.getTestItemLevelList(), testItemCategory.getId(), testItemCategory.getCreateBy());
        return AjaxResult.success();
    }

    /**
     * 批量删除测试项目分类
     *
     * @param ids 需要删除的测试项目分类主键
     * @return 结果
     */
    @Override
    public int deleteTestItemCategoryByIds(Long[] ids) {
        return testItemCategoryMapper.deleteTestItemCategoryByIds(ids);
    }

    /**
     * 删除测试项目分类信息
     *
     * @param id 测试项目分类主键
     * @return 结果
     */
    @Override
    public int deleteTestItemCategoryById(Long id) {
        return testItemCategoryMapper.deleteTestItemCategoryById(id);
    }

    /**
     * 逻辑删除分类信息
     *
     * @param ids 需要删除的测试项目分类主键集合
     * @return int 数量
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateTestItemCategoryByIds(Long[] ids) {
        //删除测试项目分类主表信息
        int itemCategoryCount = testItemCategoryMapper.updateTestItemCategoryByIds(ids);
        if (itemCategoryCount <= 0) {
            throw new ServiceException("删除测试项目分类信息失败");
        }
        //删除测试项目分类级别信息表信息
        int levelCategoryCount = testItemLevelMapper.getTestItemLevelByCategoryIds(ids);
        if (levelCategoryCount > 0) {
            int deleteLevelCount = testItemLevelMapper.updateTestItemLevelByCategoryIds(ids);
            if (deleteLevelCount <= 0) {
                throw new ServiceException("删除测试项目分类级别信息失败");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 新增测试分类区间得分信息
     *
     * @param testItemLevelList 区间得分列表
     * @param categoryId        分类id
     * @param createBy          创建热
     */
    private void insertCategoryLevelInfo(List<TestItemLevel> testItemLevelList, Long categoryId, String createBy) {
        if (CollectionUtils.isNotEmpty(testItemLevelList)) {
            //判断区间分数是否正确，目前仅支持所有的得分区间都是闭区间
            judgeLevelScore(testItemLevelList);
            //新增分类得分区间信息
            for (TestItemLevel level : testItemLevelList) {
                if (Objects.nonNull(level.getLevelName()) && Objects.nonNull(level.getLevelMinScore()) && Objects.nonNull(level.getLevelMaxScore())) {
                    //插入数据
                    insertCategoryLevel(level, categoryId, createBy);
                }
            }
        }
    }

    /**
     * 判断测试项目区间分数最小值和最大值是否正确
     *
     * @param testItemLevelList 区间分组信息
     */
    private void judgeLevelScore(List<TestItemLevel> testItemLevelList) {
        //按照区间最小值进行排序
        List<TestItemLevel> itemLevelList = testItemLevelList.stream()
                .filter(item -> Objects.nonNull(item.getLevelMinScore()))
                .sorted(Comparator.comparing(TestItemLevel::getLevelMinScore)).collect(Collectors.toList());
        for (int i = 0; i < itemLevelList.size(); i++) {
            TestItemLevel testItemLevel = itemLevelList.get(i);
            if (Objects.nonNull(testItemLevel.getLevelMinScore()) && Objects.nonNull(testItemLevel.getLevelMaxScore())) {
                if (testItemLevel.getLevelMinScore().compareTo(testItemLevel.getLevelMaxScore()) >= 0) {
                    throw new ServiceException("测试分类最低分不能大于测试分类最高分！");
                }
            }
            //判断区间分数是否重复
            for (int j = i + 1; j < itemLevelList.size(); j++) {
                if (Objects.nonNull(itemLevelList.get(j).getLevelMinScore()) && Objects.nonNull(testItemLevel.getLevelMaxScore())) {
                    if (itemLevelList.get(j).getLevelMinScore().compareTo(testItemLevel.getLevelMaxScore()) <= 0) {
                        throw new ServiceException("测试分类最低分和测试分类最高分区间不能重复！");
                    }
                }
            }
        }
    }

    /**
     * 将测试分类分类得分区间信息保存到数据库中
     *
     * @param level      得分区间信息
     * @param categoryId 分类id
     * @param createBy   创建人
     */
    private void insertCategoryLevel(TestItemLevel level, Long categoryId, String createBy) {
        level.setItemCategoryId(categoryId);
        level.setDelFlag(0);
        level.setCreateBy(createBy);
        level.setCreateTime(DateUtils.getNowDate());
        int insertLevelCount = testItemLevelMapper.insertTestItemLevel(level);
        if (insertLevelCount <= 0) {
            throw new ServiceException("新增测试分类得分信息失败");
        }
    }
}
