


package com.ai.da.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.CopyUtil;
import com.ai.da.mapper.primary.ClassificationMapper;
import com.ai.da.mapper.primary.ClassificationRelLibraryMapper;
import com.ai.da.mapper.primary.entity.Classification;
import com.ai.da.mapper.primary.entity.ClassificationRelLibrary;
import com.ai.da.model.dto.ClassificationDTO;
import com.ai.da.model.enums.DesignElementsEnum;
import com.ai.da.model.enums.Language;
import com.ai.da.model.vo.AuthPrincipalVo;
import com.ai.da.model.vo.ClassificationVO;
import com.ai.da.service.ClassificationService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author SHAHAIBO
 * @version 1.0
 * @project aida_back
 * @description 分类 接口服务实现类
 * @date 2023/11/3 10:00:00
 */
@Slf4j
@Service
public class ClassificationServiceImpl implements ClassificationService {

    @Resource
    private ClassificationMapper classificationMapper;

    @Resource
    private ClassificationRelLibraryMapper classificationRelLibraryMapper;

    @Override
    public Boolean saveOrUpdate(ClassificationDTO classificationDTO) {
        //校验
        AuthPrincipalVo userHolder = UserContext.getUserHolder();
        classificationDTO.setUserId(userHolder.getId());
        classificationDTOCheck(classificationDTO);
        Classification classification = CopyUtil.copyObject(classificationDTO, Classification.class);
        if (null == classificationDTO.getId()) {
            // 新增
            if (null == classification.getParentId()) {
                // 一级分类parentId
                classification.setParentId(0L);
            }
            classification.setCreateTime(LocalDateTime.now());
            classification.setUserId(userHolder.getId());
            int insert = classificationMapper.insert(classification);
            if (insert == 1) {
                return Boolean.TRUE;
            }else {
                throw new BusinessException("save.classification.failed");
            }
        }else {
            // 修改
            classification.setUpdateTime(LocalDateTime.now());
            int update = classificationMapper.updateById(classification);
            if (update == 1) {
                return Boolean.TRUE;
            }else {
                throw new BusinessException("update.classification.failed");
            }
        }
    }

    @Override
    public Boolean delete(ClassificationDTO classificationDTO) {
        QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
        qw.lambda().eq(ClassificationRelLibrary::getUserId, UserContext.getUserHolder().getId());
        if (Objects.nonNull(classificationDTO.getClassificationIdList()) && !classificationDTO.getClassificationIdList().isEmpty()){
            qw.lambda().in(ClassificationRelLibrary::getClassificationId, classificationDTO.getClassificationIdList());
        }
        List<ClassificationRelLibrary> classificationRelLibraryList = classificationRelLibraryMapper.selectList(qw);
        if (0 == classificationDTO.getDeleteConfirm()) {
            // 校验删除的分类是否有关联的library数据
            if (CollectionUtil.isNotEmpty(classificationRelLibraryList)) {
                throw new BusinessException("the.classification.you.deleted.has.associated.library", ResultEnum.WARNING.getCode());
            }
        }else {
            if (CollectionUtil.isNotEmpty(classificationRelLibraryList)) {
                classificationRelLibraryMapper.delete(qw);
            }
        }
        classificationMapper.deleteBatchIds(classificationDTO.getClassificationIdList());
        return Boolean.TRUE;
    }

    @Override
    public List<ClassificationVO> queryClassification(ClassificationDTO classificationDTO) {
        AuthPrincipalVo userHolder = UserContext.getUserHolder();
        QueryWrapper<Classification> qw = new QueryWrapper<>();
        qw.lambda().eq(Classification::getUserId, userHolder.getId());
        qw.lambda().eq(Classification::getType, classificationDTO.getType());
        qw.lambda().eq(Classification::getParentId, 0L);
        List<Classification> classificationList = classificationMapper.selectList(qw);
        if (CollectionUtil.isNotEmpty(classificationList)) {
            // 获取结果集
            List<ClassificationVO> classificationVOList = getClassificationVOList(classificationList);
//            if (classificationDTO.getType().equals("DesignElements")) {
//                for (ClassificationVO classificationVO : classificationVOList) {
//                    String classificationName = classificationVO.getClassificationName();
//                    DesignElementsEnum designElementsEnum = DesignElementsEnum.fromName(classificationName);
//                    if (userHolder.getLanguage().equals(Language.ENGLISH.name())) {
//                        classificationVO.setClassificationName(designElementsEnum.getEnglish());
//                    }else {
//                        classificationVO.setClassificationName(designElementsEnum.getChinese());
//                    }
//                }
//            }
            return classificationVOList;
        }
        return new ArrayList<>();
    }

    @Override
    public List<ClassificationVO> getClassificationVOList(List<Classification> classificationList) {
        List<ClassificationVO> classificationVOS = CopyUtil.copyList(classificationList, ClassificationVO.class);
        for (ClassificationVO classificationVO : classificationVOS) {
            // 递归
            List<ClassificationVO> childList = recursionClassificationVO(classificationVO);
            if (CollectionUtil.isNotEmpty(childList)) {
                classificationVO.setChildList(childList);
            }
        }
        return classificationVOS;
    }

    @Override
    public Boolean relationLibrary(ClassificationDTO classificationDTO) {
        if (CollectionUtil.isNotEmpty(classificationDTO.getLibraryIdList())) {
            for (Long libraryId : classificationDTO.getLibraryIdList()) {
                QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
                qw.lambda().eq(ClassificationRelLibrary::getLibraryId, libraryId);
                List<ClassificationRelLibrary> classificationRelLibraryList = classificationRelLibraryMapper.selectList(qw);
                List<Long> unchangedIds = classificationRelLibraryList.stream()
                        .map(ClassificationRelLibrary::getClassificationId)
                        .filter(classificationId -> classificationDTO.getClassificationIdList().contains(classificationId))
                        .collect(Collectors.toList());
                List<Long> deleteIds = classificationRelLibraryList.stream()
                        .map(ClassificationRelLibrary::getClassificationId)
                        .filter(classificationId -> !unchangedIds.contains(classificationId))
                        .collect(Collectors.toList());
                List<Long> addIds = classificationDTO.getClassificationIdList().stream()
                        .filter(classificationId -> !unchangedIds.contains(classificationId))
                        .collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(deleteIds)) {
                    QueryWrapper<ClassificationRelLibrary> deleteQw = new QueryWrapper<>();
                    deleteQw.lambda().eq(ClassificationRelLibrary::getLibraryId, libraryId);
                    deleteQw.lambda().in(ClassificationRelLibrary::getClassificationId, deleteIds);
                    classificationRelLibraryMapper.delete(deleteQw);
                }
                if (CollectionUtil.isNotEmpty(addIds)) {
                    for (Long addId : addIds) {
                        ClassificationRelLibrary classificationRelLibrary = new ClassificationRelLibrary();
                        classificationRelLibrary.setClassificationId(addId);
                        classificationRelLibrary.setLibraryId(libraryId);
                        classificationRelLibrary.setCreateTime(LocalDateTime.now());
                        classificationRelLibrary.setIsDeleted(0);
//                classificationRelLibrary.setUserId();
                        classificationRelLibraryMapper.insert(classificationRelLibrary);
                    }
                }
            }
        }
        return Boolean.TRUE;
    }

    @Override
    public List<Long> getLibraryIdListByClassificationId(Long classificationId) {
        List<Long> treeClassificationIdList = getTreeClassificationIdListByClassificationId(classificationId);
        QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
        qw.lambda().in(ClassificationRelLibrary::getClassificationId, treeClassificationIdList);
        List<ClassificationRelLibrary> classificationRelLibraryList = classificationRelLibraryMapper.selectList(qw);
        Set<Long> collect = classificationRelLibraryList.stream()
                .map(ClassificationRelLibrary::getLibraryId)
                .collect(Collectors.toSet());
        List<Long> libraryIdList = new ArrayList<>(collect);
        return libraryIdList;
    }

    @Override
    public List<Long> getRelClassificationIdList(ClassificationDTO classificationDTO) {
        Long libraryId = classificationDTO.getLibraryIdList().get(0);
        QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
        qw.lambda().eq(ClassificationRelLibrary::getLibraryId, libraryId);
        List<ClassificationRelLibrary> classificationRelLibraryList = classificationRelLibraryMapper.selectList(qw);
        if (CollectionUtil.isNotEmpty(classificationRelLibraryList)) {
            return classificationRelLibraryList.stream()
                    .map(ClassificationRelLibrary::getClassificationId)
                    .collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public List<Long> getRelPublicClassificationIdList(ClassificationDTO classificationDTO) {
        List<Long> libraryIdList = classificationDTO.getLibraryIdList();
        if (CollectionUtil.isEmpty(libraryIdList)) {
            throw new BusinessException("libraryIdList.cannot.be.empty");
        }
        List<Long> classificationIdList = new ArrayList<>();
        // 遍历获取library关联的公共标签，返回给前端
        for (int i = 0; i < libraryIdList.size(); i++) {
            QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
            qw.lambda().eq(ClassificationRelLibrary::getLibraryId, libraryIdList.get(i));
            List<Long> collect = classificationRelLibraryMapper.selectList(qw)
                    .stream()
                    .map(ClassificationRelLibrary::getClassificationId)
                    .distinct()
                    .collect(Collectors.toList());
            if (i == 0) {
                classificationIdList.addAll(collect);
            }else {
                classificationIdList.retainAll(collect);
            }
        }
        return classificationIdList;
    }

    @Override
    public Boolean editRelPublicClassificationIdList(ClassificationDTO classificationDTO) {
        List<Long> relPublicClassificationIdList = getRelPublicClassificationIdList(classificationDTO);
        List<Long> deleteIdList = relPublicClassificationIdList.stream()
                .filter(item -> !classificationDTO.getClassificationIdList().contains(item))
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(deleteIdList)) {
            for (Long libraryId : classificationDTO.getLibraryIdList()) {
                QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
                qw.lambda().eq(ClassificationRelLibrary::getLibraryId, libraryId);
                qw.lambda().in(ClassificationRelLibrary::getClassificationId, deleteIdList);
                classificationRelLibraryMapper.delete(qw);
            }
        }
        List<Long> addIdList = classificationDTO.getClassificationIdList().stream()
                .filter(item -> !relPublicClassificationIdList.contains(item))
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(addIdList)) {
            for (Long libraryId : classificationDTO.getLibraryIdList()) {
                for (Long classificationId : addIdList) {
                    QueryWrapper<ClassificationRelLibrary> qw = new QueryWrapper<>();
                    qw.lambda().eq(ClassificationRelLibrary::getLibraryId, libraryId);
                    qw.lambda().eq(ClassificationRelLibrary::getClassificationId, classificationId);
                    List<ClassificationRelLibrary> exist = classificationRelLibraryMapper.selectList(qw);
                    if (CollectionUtil.isEmpty(exist)) {
                        ClassificationRelLibrary classificationRelLibrary = new ClassificationRelLibrary();
                        classificationRelLibrary.setClassificationId(classificationId);
                        classificationRelLibrary.setLibraryId(libraryId);
                        classificationRelLibrary.setCreateTime(LocalDateTime.now());
                        classificationRelLibrary.setIsDeleted(0);
                        classificationRelLibraryMapper.insert(classificationRelLibrary);
                    }
                }
            }
        }
        return Boolean.TRUE;
    }

    private List<Long> getTreeClassificationIdListByClassificationId(Long classificationId) {
        List<Long> classificationIdList = new ArrayList<>();
        classificationIdList.add(classificationId);
        QueryWrapper<Classification> qw = new QueryWrapper<>();
        qw.lambda().eq(Classification::getParentId, classificationId);
        List<Classification> childList = classificationMapper.selectList(qw);
        if (CollectionUtil.isNotEmpty(childList)) {
            for (Classification child : childList) {
                List<Long> childTree = getTreeClassificationIdListByClassificationId(child.getId());
                if (CollectionUtil.isNotEmpty(childTree)) {
                    classificationIdList.addAll(childTree);
                }
            }
        }
        return classificationIdList;
    }

    private List<ClassificationVO> recursionClassificationVO(ClassificationVO classificationVO) {
        QueryWrapper<Classification> qw = new QueryWrapper<>();
        qw.lambda().eq(Classification::getParentId, classificationVO.getId());
        List<Classification> classificationChildList = classificationMapper.selectList(qw);
        if (CollectionUtil.isEmpty(classificationChildList)) {
            return new ArrayList<>();
        }
        List<ClassificationVO> classificationChildVOList = CopyUtil.copyList(classificationChildList, ClassificationVO.class);
        for (ClassificationVO classificationChildVO : classificationChildVOList) {
            // 递归
            List<ClassificationVO> childList = recursionClassificationVO(classificationChildVO);
            if (CollectionUtil.isNotEmpty(childList)) {
                classificationChildVO.setChildList(childList);
            }
        }
        return classificationChildVOList;
    }

    private void classificationDTOCheck(ClassificationDTO classificationDTO) {
        if (StringUtils.isEmpty(classificationDTO.getType())) {
            throw new BusinessException("type.cannot.be.empty");
        }
        if (StringUtils.isEmpty(classificationDTO.getClassificationName())) {
            throw new BusinessException("classificationName.cannot.be.empty");
        }
        QueryWrapper<Classification> qw = new QueryWrapper<>();
        qw.lambda().eq(Classification::getUserId, classificationDTO.getUserId());
        qw.lambda().ne(null != classificationDTO.getId(), Classification::getId, classificationDTO.getId());
        qw.lambda().eq(Classification::getType, classificationDTO.getType());
        if (null == classificationDTO.getParentId()) {
            qw.lambda().eq(Classification::getParentId, 0L);
        }else {
            qw.lambda().eq(Classification::getParentId, classificationDTO.getParentId());
        }
        qw.lambda().eq(Classification::getClassificationName, classificationDTO.getClassificationName());
        List<Classification> classificationList = classificationMapper.selectList(qw);
        if (CollectionUtil.isNotEmpty(classificationList)) {
            throw new BusinessException("classificationName.already.exists", ResultEnum.PROMPT.getCode());
        }
    }
}
