package com.ai.da.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.ai.da.common.config.FileProperties;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.enums.*;
import com.ai.da.common.utils.*;
import com.ai.da.mapper.primary.DesignMapper;
import com.ai.da.mapper.primary.GenerateDetailMapper;
import com.ai.da.mapper.primary.TDesignPythonOutfitMapper;
import com.ai.da.mapper.primary.entity.*;
import com.ai.da.mapper.primary.entity.Collection;
import com.ai.da.model.dto.*;
import com.ai.da.model.vo.*;
import com.ai.da.python.PythonService;
import com.ai.da.python.vo.*;
import com.ai.da.service.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ai.da.python.vo.DesignPythonItem.*;

/**
 * 服务实现类
 *
 * @author yanglei
 * @since 2022-09-30
 */
@Slf4j
@Service
public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> implements DesignService {
    @Resource
    private DesignMapper designMapper;
    @Resource
    private CollectionElementService collectionElementService;
    @Resource
    private CollectionService collectionService;
    @Resource
    private PythonService pythonService;
    @Resource
    private LibraryService libraryService;
    @Resource
    private GenerateDetailMapper generateDetailMapper;
    @Resource
    private DesignItemService designItemService;
    @Resource
    private DesignItemDetailService designItemDetailService;
    @Resource
    private FileProperties fileProperties;
    @Resource
    private UserLikeGroupService userLikeGroupService;
    @Resource
    private UserLikeService userLikeService;
    @Resource
    private SysFileService sysFileService;
    @Resource
    private TCollectionElementRelationService tCollectionElementRelationService;
    @Resource
    private ITDesignPythonOutfitService designPythonOutfitService;
    @Resource
    private ITDesignPythonOutfitDetailService designPythonOutfitDetailService;
    @Resource
    private PanToneService panToneService;
    @Resource
    private PythonTAllInfoService pythonTAllInfoService;
    @Resource
    private DesignItemDetailPrintService designItemDetailPrintService;

    @Resource
    private TDesignPythonOutfitMapper designPythonOutfitMapper;

    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.bucketName.results}")
    private String bucketName;

    @Value("${access.python.ip:''}")
    private String accessPythonIp;
    
    @Value("${access.python.port:''}")
    private String accessPythonPort;

    @Override
    public DesignCollectionVO designCollection(DesignCollectionDTO designDTO) {
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
        //校验collection element
        ValidateElementVO elementVO = collectionElementService.validateElement(designDTO);
        //design
        return designOrRedesignOperateNew(designDTO, userInfo, null, elementVO);
    }

    private void calculateLibraryAndSysFile(DesignCollectionDTO designDTO, ValidateElementVO elementVO, AuthPrincipalVo userInfo) {
        //查询用户 sketch library
        List<LibraryVo> libraryVos;
        if (CollectionUtil.isNotEmpty(designDTO.getSketchBoards())) {
            List<String> sketchUrlList = elementVO.getSketchBoardElements()
                    .stream()
                    .map(CollectionElement::getUrl)
                    .collect(Collectors.toList());
            DesignAttributeRetrievalDTO designAttributeRetrievalDTO =
                    pythonService.generateAttributeRetrieval(sketchUrlList, userInfo.getId(), elementVO.getModelSex());
            if (CollectionUtils.isEmpty(designAttributeRetrievalDTO.getLibraryUrls())) {
                libraryVos = null;
            } else {
                libraryVos = libraryService.getByUrlList(designAttributeRetrievalDTO.getLibraryUrls(), userInfo.getId());
            }
            List<SysFileVO> sysFileVOS = sysFileService.getByUrlList(designAttributeRetrievalDTO.getSysFileUrlS());
            elementVO.setSysFileVo(sysFileVOS);
        } else {
            libraryVos = libraryService.selectByAccountIdAnd1TypeList(userInfo.getId(),
                    Collections.singletonList(CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()));
        }
        elementVO.setLibraryVos(libraryVos);
        //校验比列
        validateRatio(designDTO, libraryVos);
    }

    private void validateRatio(DesignCollectionDTO designDTO, List<LibraryVo> libraryVos) {
        //校验系统比列,先去掉 考虑到程序已经进入比较后面了,该校验不重要,且会产生脏数据
//        BigDecimal bigDecimal = designDTO.getSystemScale();
//        //池子是包括三部分 = 本次用户上传的sketch + library的sketch +系统的sketch,systemScale计算的是 library和sysFile的比列
//        if (/*CollectionUtil.isEmpty(designDTO.getSketchBoards())
//                && */CollectionUtils.isEmpty(libraryVos)
//                && bigDecimal.compareTo(BigDecimal.ZERO) <= 0) {
//            throw new BusinessException("No sketch, please increase the system rate");
//        }
    }

    private void saveCollectionElemntsByLibrarys(ValidateElementVO elementVO, Long collectionId) {
        if (CollectionUtils.isEmpty(elementVO.getLibraryCollectionElements())) {
            return;
        }
        elementVO.getLibraryCollectionElements()
                .forEach(element -> {
                    element.setCollectionId(collectionId);
                    Byte hasPin = element.getHasPin();
                    if (Objects.isNull(hasPin)) {
                        element.setHasPin((byte) 0);
                    }
                    element.setId(null);
                });
        List<CollectionElement> saveElements = elementVO.getLibraryCollectionElements();
        collectionElementService.saveBatch(saveElements);
        elementVO.getUsedElementIds().addAll(saveElements.stream().map(CollectionElement::getId).collect(Collectors.toList()));
        //sketch
        List<CollectionElement> newSketchAboard = saveElements.stream()
                .filter(f -> f.getLevel1Type().equals(CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(newSketchAboard)) {
            elementVO.getSketchBoardElements().addAll(newSketchAboard);
        }
        //print
        List<CollectionElement> newPrintboard = saveElements.stream()
                .filter(f -> f.getLevel1Type().equals(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(newPrintboard)) {
            elementVO.getPrintBoardElements().addAll(newPrintboard);
        }
        //mood
        List<CollectionElement> newMoodboard = saveElements.stream()
                .filter(f -> f.getLevel1Type().equals(CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(newMoodboard)) {
            if (CollectionUtils.isEmpty(elementVO.getMoodBoardElements())) {
                elementVO.setMoodBoardElements(new ArrayList<>());
            }
            elementVO.getMoodBoardElements().addAll(newMoodboard);
        }
    }

    private void saveCollectionElemntsByGenerates(ValidateElementVO elementVO, Long collectionId) {
        if (CollectionUtils.isEmpty(elementVO.getGenerateCollectionElements())) {
            return;
        }
        elementVO.getGenerateCollectionElements()
                .forEach(element -> {
                    element.setCollectionId(collectionId);
                    Byte hasPin = element.getHasPin();
                    if (Objects.isNull(hasPin)) {
                        element.setHasPin((byte) 0);
                    }
                    element.setId(null);
//                    element.setType(DesignTypeEnum.GENERATE.getRealName());
                });
        List<CollectionElement> saveElements = elementVO.getGenerateCollectionElements();
        collectionElementService.saveBatch(saveElements);
        elementVO.getUsedElementIds().addAll(saveElements.stream().map(CollectionElement::getId).collect(Collectors.toList()));
        //sketch
        List<CollectionElement> newSketchAboard = saveElements.stream()
                .filter(f -> f.getLevel1Type().equals(CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(newSketchAboard)) {
            elementVO.getSketchBoardElements().addAll(newSketchAboard);
        }
        //print
        List<CollectionElement> newPrintboard = saveElements.stream()
                .filter(f -> f.getLevel1Type().equals(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(newPrintboard)) {
            elementVO.getPrintBoardElements().addAll(newPrintboard);
        }
        //mood
        List<CollectionElement> newMoodboard = saveElements.stream()
                .filter(f -> f.getLevel1Type().equals(CollectionLevel1TypeEnum.MOOD_BOARD.getRealName()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(newMoodboard)) {
            if (CollectionUtils.isEmpty(elementVO.getMoodBoardElements())) {
                elementVO.setMoodBoardElements(new ArrayList<>());
            }
            elementVO.getMoodBoardElements().addAll(newMoodboard);
        }
    }

//    private DesignCollectionVO designOrRedesignOperate(DesignCollectionDTO designDTO, AuthPrincipalVo userInfo,
//                                                       Long collectionIdParam, ValidateElementVO elementVO) {
//        if (CollectionUtil.isNotEmpty(designDTO.getSketchBoards())) {
//            //编辑sketchBoard
//            collectionElementService.editSketchBoardsElement(elementVO, designDTO.getSketchBoards());
//        }
//        if (CollectionUtil.isNotEmpty(designDTO.getPrintBoards())) {
//            //编辑printBoard
//            collectionElementService.editPrintBoardsElement(elementVO, designDTO.getPrintBoards());
//        }
//        //保存collection
//        Long collectionId = (null == collectionIdParam) ?
//                collectionService.saveCollection(userInfo.getId(), designDTO.getTimeZone(), designDTO.getMoodTemplateId()) : collectionIdParam;
//        List<Long> elementIds = getElementId(elementVO);
//        //批量关联element 到 collection
//        collectionElementService.relationCollection(elementIds, collectionId);
//        //library转化为collection(生成)
//        saveCollectionElemntsByLibrarys(elementVO, collectionId);
//        //保存颜色版
//        List<CollectionElementVO> colorElementList = collectionElementService.saveColorBoard(designDTO.getColorBoards(), collectionId, designDTO.getTimeZone());
//        //保存design
//        Long designId = saveOne(designDTO, collectionId, userInfo.getId());
//        //计算library
//        calculateLibraryAndSysFile(designDTO, elementVO, userInfo);
//        //组装design入参
//        DesignPythonObjects pythonObjects = pythonService.covertDesignParam(designDTO.getSystemScale(),
//                designDTO.getSingleOverall(), designDTO.getSwitchCategory(), elementVO, designDTO.getProcessId());
//        //缓存保存的文件 方便后面处理进度问题 采用新的进度条获取方式 根据processId获取
////        setDesignProcess(userInfo.getId(), pythonObjects);
//        //design
//        pythonService.design(pythonObjects);
//        //生成library
//        generateLibrary(elementVO, designDTO.getTimeZone());
//        //处理关联关系,修复element覆盖得情况
//        List<CollectionElement> reLationelements = collectionElementService.getByOnlyCollectionId(collectionId);
//        List<Long> reLationelementIds = reLationelements.stream().map(CollectionElement::getId).collect(Collectors.toList());
//        handleCollectionElementRelation(collectionId, (null == collectionIdParam) ? false : true, reLationelementIds);
//        //保存python返回信息
////        return savePythonDesignItemAndDetail(pythonObjects,designId,collectionId,userInfo,designDTO.getTimeZone(),responseJSONObject);
//        //保存designItem 和detail
//        return saveDesignItemAndDetail(pythonObjects, designId, collectionId, userInfo, designDTO.getTimeZone());
//    }

    private DesignCollectionVO designOrRedesignOperateNew(DesignCollectionDTO designDTO, AuthPrincipalVo userInfo,
                                                          Long collectionIdParam, ValidateElementVO elementVO) {
        if (CollectionUtil.isNotEmpty(designDTO.getSketchBoards())) {
            //编辑sketchBoard
            collectionElementService.editSketchBoardsElement(elementVO, designDTO.getSketchBoards());
        }
        if (CollectionUtil.isNotEmpty(designDTO.getPrintBoards())) {
            //编辑printBoard
            collectionElementService.editPrintBoardsElement(elementVO, designDTO.getPrintBoards());
        }
        //保存collection
        Long collectionId = (null == collectionIdParam) ?
                collectionService.saveCollection(userInfo.getId(), designDTO.getTimeZone(), designDTO.getMoodTemplateId()) : collectionIdParam;
        List<Long> elementIds = getElementId(elementVO);
        //批量关联element 到 collection
        collectionElementService.relationCollection(elementIds, collectionId);
        //library转化为collection(生成)
        saveCollectionElemntsByLibrarys(elementVO, collectionId);
        //generate转化为collection(生成)
        saveCollectionElemntsByGenerates(elementVO, collectionId);
        //保存颜色版
        List<CollectionElementVO> colorElementList = collectionElementService.saveColorBoard(designDTO.getColorBoards(), collectionId, designDTO.getTimeZone());
        //保存design
        Long designId = saveOne(designDTO, collectionId, userInfo.getId());
        //计算library
//        calculateLibraryAndSysFile(designDTO, elementVO, userInfo);
        //组装design入参
        long startTime = System.currentTimeMillis();
        DesignPythonObjects pythonObjects = pythonService.covertDesignParam(designDTO.getSystemScale(),
                designDTO.getSingleOverall(), designDTO.getSwitchCategory(), elementVO, designDTO.getProcessId());
        long endTime = System.currentTimeMillis();
        long totalTimeInSeconds = (endTime - startTime) / 1000;
        log.info("组装入参运行时间：" + totalTimeInSeconds + " 秒");
        // pythonObjects增加image_id关联
        startTime = System.currentTimeMillis();
        List<Long> imageIds = relationImageIds(pythonObjects);
        endTime = System.currentTimeMillis();
        totalTimeInSeconds = (endTime - startTime) / 1000;
        log.info("增加image_id关联运行时间：" + totalTimeInSeconds + " 秒");
        //design
        startTime = System.currentTimeMillis();
        JSONObject responseJSONObject = pythonService.designNew(pythonObjects);
        endTime = System.currentTimeMillis();
        totalTimeInSeconds = (endTime - startTime) / 1000;
        log.info("design python端运行时间：" + totalTimeInSeconds + " 秒");
        //生成library
        startTime = System.currentTimeMillis();
        generateLibrary(elementVO, designDTO.getTimeZone());
        //处理关联关系,修复element覆盖得情况
        List<CollectionElement> relationElements = collectionElementService.getByOnlyCollectionId(collectionId);
        List<Long> relationElementIds = relationElements.stream().map(CollectionElement::getId).collect(Collectors.toList());
        handleCollectionElementRelation(collectionId, null != collectionIdParam, relationElementIds);
        endTime = System.currentTimeMillis();
        totalTimeInSeconds = (endTime - startTime) / 1000;
        log.info("处理关联关系运行时间：" + totalTimeInSeconds + " 秒");
        //保存python返回信息;保存designItem和detail
        return savePythonDesignItemAndDetail(pythonObjects, designId, collectionId, userInfo, designDTO.getTimeZone(), responseJSONObject, designDTO.getSingleOverall());
    }

    @Override
    public void relationImageId(DesignPythonObjects pythonObjects) {
        if (Objects.isNull(pythonObjects)) {
            return;
        }
        pythonObjects.getObjects().forEach(
                o -> {
                    for (DesignPythonItem item : o.getItems()) {
                        List<Long> list = new ArrayList<>();
                        list.add(1L);
                        list.add(1L);
                        item.setOffset(list);
                        item.setResize_scale(1f);
                        String path = item.getPath();
                        if (StringUtils.isEmpty(path)) {
                            String bodyPath = item.getBody_path();
                            Long imageId = pythonTAllInfoService.getImageIdByPath(bodyPath);
                            item.setImage_id(imageId);
                        } else {
                            Long imageId = pythonTAllInfoService.getImageIdByPath(path);
                            item.setImage_id(imageId);
                        }
                    }
                }
        );
    }

    @Override
    public List<CollectionSketchVO> sketchesBoundingBox(SketchesBoundingBoxDTO sketchesBoundingBoxDTO) {
        List<CollectionSketchDTO> sketchBoards = sketchesBoundingBoxDTO.getSketchBoards();
        if (CollectionUtil.isNotEmpty(sketchBoards)) {
            List<CollectionSketchVO> result = new ArrayList<>();
            List<CollectionSketchDTO> collect = sketchBoards.stream()
                    .filter(o -> !o.getDesignType().equals(DesignTypeEnum.LIBRARY.getRealName()))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(collect)) {
                for (CollectionSketchDTO collectionSketchDTO : collect) {
                    CollectionSketchVO vo = CopyUtil.copyObject(collectionSketchDTO, CollectionSketchVO.class);
                    if (collectionSketchDTO.getDesignType().equals(DesignTypeEnum.COLLECTION.getRealName())) {
                        CollectionElement byId = collectionElementService.getById(collectionSketchDTO.getSketchBoardId());
                        libraryService.processSketchBoards(byId.getUrl(), collectionSketchDTO.getLevel2Type());
                        String url = byId.getUrl();
                        if (url.contains(".")) {
                            String[] split = url.split("\\.");
                            vo.setUrlWithWhiteSide(minioUtil.getPresignedUrl(split[0] + "-show." + split[1], 24 * 60));
                        }else {
                            vo.setUrlWithWhiteSide(minioUtil.getPresignedUrl(url + "-show", 24 * 60));
                        }
                        result.add(vo);
                    }else if (collectionSketchDTO.getDesignType().equals(DesignTypeEnum.GENERATE.getRealName())) {
                        GenerateDetail generateDetail = generateDetailMapper.selectById(collectionSketchDTO.getSketchBoardId());
                        libraryService.processSketchBoards(generateDetail.getUrl(), collectionSketchDTO.getLevel2Type());
                        String url = generateDetail.getUrl();
                        if (url.contains(".")) {
                            String[] split = url.split("\\.");
                            vo.setUrlWithWhiteSide(minioUtil.getPresignedUrl(split[0] + "-show." + split[1], 24 * 60));
                        }else {
                            vo.setUrlWithWhiteSide(minioUtil.getPresignedUrl(url + "-show", 24 * 60));
                        }
                        result.add(vo);
                    }
                }
            }
            List<CollectionSketchDTO> libraryList = sketchBoards.stream()
                    .filter(o -> o.getDesignType().equals(DesignTypeEnum.LIBRARY.getRealName()))
                    .collect(Collectors.toList());
            for (CollectionSketchDTO collectionSketchDTO : libraryList) {
                Library byId = libraryService.getById(collectionSketchDTO.getSketchBoardId());
                libraryService.processSketchBoards(byId.getUrl(), collectionSketchDTO.getLevel2Type());
                CollectionSketchVO vo = CopyUtil.copyObject(collectionSketchDTO, CollectionSketchVO.class);
                String url = byId.getUrl();
                if (url.contains(".")) {
                    String[] split = url.split("\\.");
                    vo.setUrlWithWhiteSide(minioUtil.getPresignedUrl(split[0] + "-show." + split[1], 24 * 60));
                }else {
                    vo.setUrlWithWhiteSide(minioUtil.getPresignedUrl(url + "-show", 24 * 60));
                }
                result.add(vo);
            }
            return result;
        }
        return new ArrayList<>();
    }

    public List<Long> relationImageIds(DesignPythonObjects pythonObjects) {
        List<Long> imageIds = new ArrayList<>();
        if (Objects.isNull(pythonObjects)) {
            return imageIds;
        }
        pythonObjects.getObjects().forEach(
                o -> {
                    for (DesignPythonItem item : o.getItems()) {
                        List<Long> list = new ArrayList<>();
                        list.add(1L);
                        list.add(1L);
                        item.setOffset(list);
                        item.setResize_scale(1f);
                        String path = item.getPath();
                        if (StringUtils.isEmpty(path)) {
                            String bodyPath = item.getBody_path();
                            Long imageId = pythonTAllInfoService.getImageIdByPath(bodyPath);
                            imageIds.add(imageId);
                            item.setImage_id(imageId);
                        } else {
                            Long imageId = pythonTAllInfoService.getImageIdByPath(path);
                            imageIds.add(imageId);
                            item.setImage_id(imageId);
                        }
                    }
                }
        );
        return imageIds;
    }

    private void handleCollectionElementRelation(Long collectionId, Boolean isEdit, List<Long> elementIds) {
        if (CollectionUtils.isEmpty(elementIds) || collectionId == null) {
            return;
        }
        if (isEdit) {
            //删除
            tCollectionElementRelationService.deleteByCollectionId(collectionId);
        }
        //新增
        tCollectionElementRelationService.saveBatch(elementIds.stream().map(elementId ->
                TCollectionElementRelation.builder()
                        .collectionId(collectionId)
                        .elementId(elementId)
                        .createDate(new Date())
                        .build()
        ).collect(Collectors.toList()));
    }

    private void generateLibrary(ValidateElementVO elementVO, String timeZone) {
        List<CollectionElement> elements = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(elementVO.getMoodBoardElements())) {
            elements.addAll(elementVO.getMoodBoardElements());
        }
        if (!CollectionUtils.isEmpty(elementVO.getPrintBoardElements())) {
            elements.addAll(elementVO.getPrintBoardElements());
        }
        if (!CollectionUtils.isEmpty(elementVO.getSketchBoardElements())) {
            elements.addAll(elementVO.getSketchBoardElements());
        }
        if (!CollectionUtils.isEmpty(elementVO.getMarketingSketchElements())) {
            elements.addAll(elementVO.getMarketingSketchElements());
        }
        collectionElementService.saveLibraryByCollectionElement(elements, timeZone, elementVO.getModelSex());
    }

    @Override
    public BigDecimal countDesignProcess() {
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
        List<String> saveNames = LocalCacheUtils.getDesignProcessCache(userInfo.getId());
        if (CollectionUtils.isEmpty(saveNames)) {
            return BigDecimal.ZERO;
        }
        int totalProcess = 0;
        log.info("design 统计进度###totalProcess1{}", totalProcess);
        //转成本地文件先
        for (String saveName : saveNames) {
            String localFileUrl = saveName;
            String linuxDomain = fileProperties.getLinuxDomain();
            if (!StringUtils.isEmpty(linuxDomain)) {
                //linux 系统
                String oldPath = fileProperties.getSys().getPath();
                localFileUrl = saveName.replace(linuxDomain, oldPath);
            }
            File file = new File(localFileUrl);
            if (file.exists()) {
                totalProcess++;
                log.info("design 统计进度++###totalProcess+++{}", totalProcess);
            }
        }
        log.info("design 统计进度###totalProcess2{}", totalProcess);
        BigDecimal result = BigDecimal.valueOf(totalProcess).divide(BigDecimal.valueOf(8)).setScale(3, BigDecimal.ROUND_HALF_UP);
        if (result.compareTo(BigDecimal.ONE) == 0) {
            LocalCacheUtils.delDesignProcessCache(userInfo.getId());
        }
        return result;
    }

    private void setDesignProcess(Long userId, DesignPythonObjects pythonObjects) {
        List<String> saveNames = pythonObjects.getObjects().stream().map(object -> {
            return object.getBasic().getSave_name();
        }).collect(Collectors.toList());
        LocalCacheUtils.setDesignProcessCache(userId, saveNames);
    }

    @Resource
    private MinioUtil minioUtil;

    private DesignCollectionVO savePythonDesignItemAndDetail(DesignPythonObjects pythonObjects
            , Long designId, Long collectionId, AuthPrincipalVo userInfo, String timeZone, JSONObject responseJSONObject, String singleOverall) {
        DesignCollectionVO response = new DesignCollectionVO();
        response.setDesignId(designId);
        response.setCollectionId(collectionId);
        List<DesignCollectionItemVO> designCollectionItems = Lists.newArrayList();
        response.setDesignCollectionItems(designCollectionItems);
        JSONObject data = responseJSONObject.getJSONObject("data");
        if (data == null) {
            throw new BusinessException("design.interface.exception");
        }
        for (int i = 0; i < pythonObjects.getObjects().size(); i++) {
            DesignPythonObject item = pythonObjects.getObjects().get(i);
            DesignItem designItem = new DesignItem();
            designItem.setAccountId(userInfo.getId());
            designItem.setCollectionId(collectionId);
            designItem.setDesignId(designId);
            designItem.setCreateDate(DateUtil.getByTimeZone(timeZone));
            //生成的八张图片
            designItem.setDesignUrl(item.getBasic().getSave_name());
            designItem.setHasLike((byte) 0);
            //生成designItem
            Long designItemId = designItemService.saveOne(designItem);
            // python design返回入库及封装
            JSONObject outfit = data.getJSONObject(i + "");
            if (null == outfit) {
                continue;
            }
            TDesignPythonOutfit designPythonOutfit = new TDesignPythonOutfit();
            designPythonOutfit.setDesignItemId(designItemId);
            designPythonOutfit.setUserId(userInfo.getId());
            designPythonOutfit.setDesignId(designId);
            designPythonOutfit.setCollectionId(collectionId);
            String synthesisUrl = outfit.getString("synthesis_url");
            if (!StringUtils.isEmpty(synthesisUrl)) {
                designPythonOutfit.setDesignUrl(synthesisUrl);
            } else {
                throw new BusinessException("design.interface.exception");
            }
            designPythonOutfitService.save(designPythonOutfit);
            JSONArray layers = outfit.getJSONArray("layers");
            List<TDesignPythonOutfitDetail> list = new ArrayList<>();
            DesignCollectionItemVO designCollectionItemVO = new DesignCollectionItemVO();
            for (int i1 = 0; i1 < layers.size(); i1++) {
                JSONObject jsonObject = layers.getJSONObject(i1);
                TDesignPythonOutfitDetail designPythonOutfitDetail = new TDesignPythonOutfitDetail();
                designPythonOutfitDetail.setDesignId(designId);
                designPythonOutfitDetail.setDesignPythonOutfitId(designPythonOutfit.getId());
                designPythonOutfitDetail.setPosition(jsonObject.getString("position"));
                designPythonOutfitDetail.setImageSize(jsonObject.getString("image_size"));
                designPythonOutfitDetail.setImageUrl(jsonObject.getString("image_url"));
                if (singleOverall.equals(SingleOverallEnum.SINGLE.getRealName())) {
                    designCollectionItemVO.setDesignItemUrl(designItem.getDesignUrl());
                }
                designPythonOutfitDetail.setImageCategory(jsonObject.getString("image_category"));
                designPythonOutfitDetail.setMaskUrl(jsonObject.getString("mask_url"));
                designPythonOutfitDetail.setUserId(userInfo.getId());
                designPythonOutfitDetail.setPriority(Integer.parseInt(jsonObject.getString("priority")));
                list.add(designPythonOutfitDetail);
            }
            designPythonOutfitDetailService.saveBatch(list);
            designCollectionItemVO.setDesignItemId(designItemId);
            designCollectionItemVO.setDesignItemUrl(designItem.getDesignUrl());
            designCollectionItemVO.setDesignOutfitId(designPythonOutfit.getId());
            String designUrl = designPythonOutfit.getDesignUrl();
            if (!StringUtils.isEmpty(designUrl) && designUrl.contains("/")) {
                int firstIndex = designUrl.indexOf("/");
                designCollectionItemVO.setDesignOutfitUrl(minioUtil.getPresignedUrl(designUrl.substring(0, firstIndex) + "/" + designUrl.substring(firstIndex + 1), 24 * 60));
            }
            //response
            designCollectionItems.add(designCollectionItemVO);

            List<DesignItemDetail> designItemDetails = Lists.newArrayList();
            Map<String, Integer> typePriority = list.stream().collect(Collectors.toMap(d -> d.getImageCategory().split("_")[0],
                                                                                        d -> Math.abs(d.getPriority()),
                                                                                        (existing, replacement) -> replacement));
            for (DesignPythonItem detail : item.getItems()) {
                if (null == detail) {
                    continue;
                }
                DesignItemDetail designItemDetail = CopyUtil.copyObject(detail, DesignItemDetail.class);
                designItemDetail.setAccountId(userInfo.getId());
                designItemDetail.setDesignId(designId);
                designItemDetail.setDesignItemId(designItemId);
                designItemDetail.setCollectionElementId(detail.getElementId());
                designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone));
                if (SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType())) {
                    designItemDetail.setPath(detail.getBody_path());
                    //BODY不关联businessId
                    designItemDetail.setBusinessId(0L);
                }
                designItemDetail.setIconPath(detail.getIcon());
                designItemDetail.setPriority(typePriority.get(detail.getType().toLowerCase()));
                DesignPythonItemPrint printObject = detail.getPrint();
                designItemDetail.setPrintPath(Objects.isNull(printObject) ? "" : printObject.getPath());
                designItemDetailService.save(designItemDetail);
                if (!SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType()) && designItemDetail.getPrintPath() != null) {
                    DesignItemDetailPrint print = new DesignItemDetailPrint();
                    print.setDesignItemDetailId(designItemDetail.getId());
                    print.setPath(designItemDetail.getPrintPath());
                    print.setSingleOrOverall("overall");
                    print.setPosition("[0.0,0.0]");
                    print.setScale(1d);
                    print.setAngle(0.0);
                    print.setPriority(1);
                    print.setCreateDate(LocalDateTime.now());
                    designItemDetailPrintService.save(print);
                }
            }
        }
        response.setProcessId(pythonObjects.getProcess_id());
        return response;
    }

    private DesignCollectionVO saveDesignItemAndDetail(DesignPythonObjects pythonObjects
            , Long designId, Long collectionId, AuthPrincipalVo userInfo, String timeZone) {
        DesignCollectionVO response = new DesignCollectionVO();
        response.setDesignId(designId);
        response.setCollectionId(collectionId);
        List<DesignCollectionItemVO> designCollectionItems = Lists.newArrayList();
        response.setDesignCollectionItems(designCollectionItems);

        pythonObjects.getObjects().forEach(item -> {
            DesignItem designItem = new DesignItem();
            designItem.setAccountId(userInfo.getId());
            designItem.setCollectionId(collectionId);
            designItem.setDesignId(designId);
            designItem.setCreateDate(DateUtil.getByTimeZone(timeZone));
            //生成的八张图片
            designItem.setDesignUrl(item.getBasic().getSave_name());
            designItem.setHasLike((byte) 0);
            //生成designItem
            Long designItemId = designItemService.saveOne(designItem);
            //response
            designCollectionItems.add(new DesignCollectionItemVO(designItemId, designItem.getDesignUrl(), null, null));

            List<DesignItemDetail> designItemDetails = Lists.newArrayList();
            item.getItems().forEach(detail -> {
                if (null == detail) {
                    return;
                }
                DesignItemDetail designItemDetail = CopyUtil.copyObject(detail, DesignItemDetail.class);
                designItemDetail.setAccountId(userInfo.getId());
                designItemDetail.setDesignId(designId);
                designItemDetail.setDesignItemId(designItemId);
                designItemDetail.setCollectionElementId(detail.getElementId());
                designItemDetail.setCreateDate(DateUtil.getByTimeZone(timeZone));
                if (SysFileLevel2TypeEnum.BODY.getRealName().equals(detail.getType())) {
                    designItemDetail.setPath(detail.getBody_path());
                    //BODY不关联businessId
                    designItemDetail.setBusinessId(0L);
                }
                designItemDetail.setIconPath(detail.getIcon());
                DesignPythonItemPrint printObject = detail.getPrint();
                designItemDetail.setPrintPath(Objects.isNull(printObject) ? "" : printObject.getPath());
                designItemDetails.add(designItemDetail);
            });
            designItemDetailService.saveBatch(designItemDetails);
        });
        return response;
    }

    private List<Long> getElementId(ValidateElementVO elementVO) {
        List<Long> elementIds = Lists.newArrayList();
        // collection type
        if (CollectionUtil.isNotEmpty(elementVO.getSketchBoardElements())) {
            elementIds.addAll(elementVO.getSketchBoardElements().stream().map(CollectionElement::getId).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(elementVO.getMoodBoardElements())) {
            elementIds.addAll(elementVO.getMoodBoardElements().stream().map(CollectionElement::getId).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(elementVO.getPrintBoardElements())) {
            elementIds.addAll(elementVO.getPrintBoardElements().stream().map(CollectionElement::getId).collect(Collectors.toList()));
        }
//        if(CollectionUtil.isNotEmpty(elementVO.getMarketingSketchElements())){
//            elementIds.addAll(elementVO.getMarketingSketchElements().stream().map(CollectionElement::getId).collect(Collectors.toList()));
//        }
        return elementIds;
    }

    @Override
    public DesignCollectionVO reDesignCollection(ReDesignCollectionDTO reDesignDTO) {
        //校验collection
        Collection collection = collectionService.getById(reDesignDTO.getCollectionId());
        if (Objects.isNull(collection)) {
            throw new BusinessException("collection.not.found");
        }
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
//        //查询用户 sketch library
//        List<LibraryVo> libraryVos = libraryService.selectByAccountIdAnd1TypeList(userInfo.getId(),
//                Arrays.asList(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName(),
//                        CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()));
        //校验collection element
        DesignCollectionDTO designCollectionDTO = CopyUtil.copyObject(reDesignDTO, DesignCollectionDTO.class);
        ValidateElementVO elementVO = collectionElementService.validateElement(designCollectionDTO);
        //计算并删除对应的未关联的element
        collectionElementService.batchDelete(
                calculateNoRelationElement(reDesignDTO.getCollectionId(), elementVO.getUsedElementIds()));
        Design oldDesign = selectByCollectionId(reDesignDTO.getCollectionId());
        //删除老的关联的design
        deleteByCollectionId(reDesignDTO.getCollectionId());
        designItemService.deleteByCollectionId(reDesignDTO.getCollectionId());
        designItemDetailService.deleteByDesignId(oldDesign.getId());
        //redesign
        return designOrRedesignOperateNew(CopyUtil.copyObject(
                reDesignDTO, DesignCollectionDTO.class), userInfo, reDesignDTO.getCollectionId(), elementVO);
    }

    private List<Long> calculateNoRelationElement(Long collectionId, List<Long> usedElementIds) {
        List<CollectionElement> collectionElements = collectionElementService.getByCollectionId(collectionId);
        if (CollectionUtils.isEmpty(collectionElements)) {
            throw new BusinessException("get collection elements cannot be empty");
        }
        if (CollectionUtils.isEmpty(usedElementIds)) {
            return collectionElements.stream().map(CollectionElement::getId).collect(Collectors.toList());
        }
        return collectionElements.stream()
                .filter(filter -> !usedElementIds.contains(filter.getId()))
                .map(CollectionElement::getId)
                .collect(Collectors.toList());
    }

    @Override
    public DesignCollectionVO designItemList(Long designId) {
        Design design = baseMapper.selectById(designId);
        if (Objects.isNull(design)) {
            throw new BusinessException("design.not.found");
        }
        List<DesignItem> designItems = designItemService.getByDesignId(designId);
        if (CollectionUtils.isEmpty(designItems)) {
            return new DesignCollectionVO(designId, design.getCollectionId(), null, null);
        }
        return new DesignCollectionVO(designId, design.getCollectionId(), coverDesignItemToVO(designItems), null);
    }

    private List<DesignCollectionItemVO> coverDesignItemToVO(List<DesignItem> designItems) {
        List<DesignCollectionItemVO> response = Lists.newArrayList();
        designItems.forEach(designItem -> {
            response.add(new DesignCollectionItemVO(designItem.getId(), designItem.getDesignUrl(), null, null));
        });
        return response;
    }

    @Override
    @Transactional
    public DesignLikeVO like(DesignLikeDTO designLikeDTO) {
        Long userGroupId = designLikeDTO.getUserGroupId();;
        Long groupDetailId;
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
        DesignItem designItem = designItemService.getById(designLikeDTO.getDesignItemId());
        if (Objects.isNull(designItem)) {
            throw new BusinessException("designItem.not.found");
        }
        String pictureName = null;
        UserLike userLike;
        if (Objects.nonNull(userGroupId)) {
            UserLikeGroup userLikeGroup = userLikeGroupService.getById(userGroupId);
            if (Objects.isNull(userLikeGroup)) {
                throw new BusinessException("userLikeGroup.not.found");
            }
//            if(designItem.getCollectionId().equals(userLikeGroup.getCollectionId())){
//                //相同collection直接跳过 不需要往element加元素
//                return new DesignLikeVO();
//            }
            List<CollectionElement> oldElements = collectionElementService.getByCollectionId(userLikeGroup.getCollectionId());
            if (CollectionUtil.isEmpty(oldElements)) {
                throw new BusinessException("old.elements.not.found");
            }
            List<DesignItemDetail> designItemDetails = designItemDetailService.selectByDesignItemId(designLikeDTO.getDesignItemId());
            if (CollectionUtil.isEmpty(designItemDetails)) {
                throw new BusinessException("new.designItemDetails.not.found");
            }
            //判断老的element合并到新的是否满足 数量不超过15
            List<Long> newElementIds = validateMergeElement(oldElements, designItemDetails);
            //合并,关联新的element到collection
            collectionElementService.relationCollection(newElementIds, userLikeGroup.getCollectionId());
            //处理关联关系,修复element覆盖得情况
            handleCollectionElementRelation(userLikeGroup.getCollectionId(), false, newElementIds);

            QueryWrapper<TDesignPythonOutfit> qw = new QueryWrapper<>();
            qw.lambda().eq(TDesignPythonOutfit::getDesignItemId, designLikeDTO.getDesignItemId());
            List<TDesignPythonOutfit> tDesignPythonOutfits = designPythonOutfitMapper.selectList(qw);
            if (CollectionUtils.isEmpty(tDesignPythonOutfits)) {
                throw new BusinessException("DesignItemId not found elements for ax  elements to like! [" + designLikeDTO.getDesignItemId());
            }
            userLike = resolveUserLike(userGroupId, designItem.getDesignId(),
                    designLikeDTO.getDesignItemId(), designLikeDTO.getDesignPythonOutfitId(), tDesignPythonOutfits.get(0).getDesignUrl(), designLikeDTO.getTimeZone());

        } else {
            //第一次like
            userGroupId = userLikeGroupService.insertUserGroup(userInfo.getId(), designItem.getCollectionId(), designLikeDTO.getTimeZone());
            QueryWrapper<TDesignPythonOutfit> qw = new QueryWrapper<>();
            qw.lambda().eq(TDesignPythonOutfit::getDesignItemId, designLikeDTO.getDesignItemId());
            List<TDesignPythonOutfit> tDesignPythonOutfits = designPythonOutfitMapper.selectList(qw);
            if (CollectionUtils.isEmpty(tDesignPythonOutfits)) {
                throw new BusinessException("DesignItemId not found elements for ax  elements to like! [" + designLikeDTO.getDesignItemId());
            }
            userLike = resolveUserLike(userGroupId,
                    designItem.getDesignId(), designLikeDTO.getDesignItemId(), designLikeDTO.getDesignPythonOutfitId(), tDesignPythonOutfits.get(0).getDesignUrl(), designLikeDTO.getTimeZone());
        }
        userLikeService.save(userLike);
        groupDetailId = userLike.getId();
        String designUrl = designPythonOutfitMapper.selectById(userLike.getDesignOutfitId()).getDesignUrl();
        if (designUrl.contains("/")) {
            int i = designUrl.lastIndexOf("/");
            pictureName = designUrl.substring(i + 1);
        }
        //修改designItem为like状态
        designItemService.updateLikeStatus(designLikeDTO.getDesignItemId(), (byte) 1);
        return new DesignLikeVO(userGroupId, groupDetailId, pictureName);
    }

    private List<Long> validateMergeElement(List<CollectionElement> oldElements, List<DesignItemDetail> designItemDetails) {
        List<DesignItemDetail> hasCollections = designItemDetails.stream()
                .filter(f -> Objects.nonNull(f.getCollectionElementId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(hasCollections)) {
            return null;
        }
        List<Long> oldIds = oldElements.stream().map(CollectionElement::getId).collect(Collectors.toList());
        List<Long> elementIds = hasCollections.stream().map(DesignItemDetail::getCollectionElementId).collect(Collectors.toList());
        //本次新增collection个数
        List<Long> adds = elementIds.stream().filter(id -> !oldIds.contains(id)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(adds)) {
            return null;
        }
        //校验15次
        Map<String, List<CollectionElement>> group = oldElements.stream()
                .collect(Collectors.groupingBy(CollectionElement::getLevel1Type));

        group.forEach((k, v) -> {
            List<CollectionElement> thisElement = group.get(k);
            int groupNum = calculateGroupNum(thisElement, adds);
            if (groupNum > 15) {
                throw new BusinessException("The size of element type" + k + "exceeds 15");
            }
        });
        return adds;
    }

    private int calculateGroupNum(List<CollectionElement> thisElement, List<Long> adds) {
        int num = 0;
        List<Long> groupOldIds = thisElement.stream().map(CollectionElement::getId).collect(Collectors.toList());
        for (Long add : adds) {
            if (groupOldIds.contains(add)) {
                num++;
            }
        }
        return num + thisElement.size();
    }

    private UserLike resolveUserLike(Long userGroupId, Long designId, Long designItemId, Long designPythonOutfitId, String designUrl, String timeZone) {
        UserLike userLike = new UserLike();
        userLike.setCreateDate(DateUtil.getByTimeZone(timeZone));
        userLike.setDesignId(designId);
        userLike.setUserLikeGroupId(userGroupId);
        userLike.setDesignItemId(designItemId);
        userLike.setDesignOutfitId(designPythonOutfitId);
        userLike.setUrl(designUrl);
        return userLike;
    }

    @Override
    public Boolean dislike(DisDesignLikeDTO disDesignLikeDTO) {
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
        UserLike userLike = userLikeService.getById(disDesignLikeDTO.getGroupDetailId());
        if (Objects.isNull(userLike)) {
            throw new BusinessException("history.detail.not.found");
        }
        Design design = getById(disDesignLikeDTO.getDesignId());
        if (Objects.isNull(design)) {
            throw new BusinessException("design.detail.not.found");
        }
        if (!userLike.getDesignId().equals(disDesignLikeDTO.getDesignId())) {
            //不是相同的design不会合并
            return Boolean.TRUE;
        }
        //修改designItem为dislike状态
        designItemService.updateLikeStatus(userLike.getDesignItemId(), (byte) 0);
        //删除关联的collection,先不做

        //删除对应的history
        userLikeService.removeById(disDesignLikeDTO.getGroupDetailId());
        List<UserLikeVO> userLikeVOS = userLikeService.getGroupDetail(userLike.getUserLikeGroupId());
        if (CollectionUtils.isEmpty(userLikeVOS)) {
            //group 下面没有元素时候 直接删除
            userLikeGroupService.removeById(userLike.getUserLikeGroupId());
        }
        return Boolean.TRUE;
    }

    @Override
    public String generateHighDesign(GenerateHighDesignDTO generateHighDesignDTO) {
        DesignItem designItem = designItemService.getById(generateHighDesignDTO.getDesignItemId());
        if (Objects.isNull(designItem)){
            throw new BusinessException("design.item.does.not.exist");
        }
        String highUrl = pythonService.generateHighDesign(designItem.getDesignUrl());
        //存储
        designItemService.updateDesignHighUrl(designItem.getId(), highUrl, generateHighDesignDTO.getTimeZone());
        return highUrl;
    }

    @Override
    public Boolean deleteHighDesign(GenerateHighDesignDTO generateHighDesignDTO) {
        DesignItem designItem = designItemService.getById(generateHighDesignDTO.getDesignItemId());
        if (Objects.isNull(designItem)){
            throw new BusinessException("design.item.does.not.exist");
        }
        if (StringUtils.isEmpty(designItem.getHighDesignUrl())) {
            //并发情况 ,不提示 直接返回
            return Boolean.TRUE;
        }
        //存储
        designItemService.updateDesignHighUrl(designItem.getId(), "", generateHighDesignDTO.getTimeZone());
        FileUtil.delete(designItem.getHighDesignUrl());
        return Boolean.TRUE;
    }

    @Override
    public DesignItemDetailVO detail(Long designPythonOutfitId, Long designItemId) {
        // 1、校验
        DesignItem designItem = designItemService.getById(designItemId);
        if (Objects.isNull(designItem)) {
            throw new BusinessException("designItem.not.found");
        }
        Design design = getById(designItem.getDesignId());
        if (Objects.isNull(design)) {
            throw new BusinessException("design.not.found");
        }
        List<DesignItemDetail> designItemDetails = designItemDetailService.selectByDesignItemId(designItemId);
        if (CollectionUtil.isEmpty(designItemDetails)) {
            throw new BusinessException("designItemDetails.not.found");
        }
        // 添加判断designPythonOutfitId是否存在
        TDesignPythonOutfit designPythonOutfit = new TDesignPythonOutfit();
        Boolean flag = Boolean.FALSE;
        if (Objects.nonNull(designPythonOutfitId)) {
            designPythonOutfit = designPythonOutfitService.getById(designPythonOutfitId);
            if (Objects.isNull(designPythonOutfit)) {
                throw new BusinessException("designPythonOutfit.not.found");
            }
            flag = Boolean.TRUE;
        }

        // 为没有优先级的衣服添加优先级
        designItemDetailService.setDesignItemDetailPriority(designItemDetails);

        // 2、组装返回参数
        DesignItemDetailVO response = new DesignItemDetailVO();
        response.setSingleOverall(design.getSingleOverall());
        response.setSwitchCategory(design.getSwitchCategory());
        response.setDesignItemId(designItemId);
//        response.setDesignItemUrl(designItem.getDesignUrl());
        response.setHighDesignUrl(designItem.getHighDesignUrl());
        List<DesignItemDetail> filterDetail = designItemDetails.stream()
                .filter(f -> OUTWEAR_DRESS_BLOUSE.contains(f.getType()) || SKIRT_TROUSERS.contains(f.getType())
                        || TOPS.contains(f.getType()) || BOTTOMS.contains(f.getType()))
                .collect(Collectors.toList());
        response.setClothes(CopyUtil.copyList(filterDetail, DesignItemClothesDetailVO.class, (o, d) -> {
            d.setId(o.getId());
            d.setPath(minioUtil.getPresignedUrl(o.getPath(), 24 * 60));
            d.setMinIOPath(o.getPath());
            d.setLevel1Type(converTypeToLevel1(o.getType()));
            // 根据designItemDetailId获取印花
            List<DesignItemDetailPrint> prints = designItemDetailPrintService.getByDesignItemDetailId(o.getId());
            // 判断有无印花
            if (CollectionUtil.isNotEmpty(prints)) {
                // 有印花
                d.setPrintObject(convertToDesignSinglePrintDTO(prints));
            }
//            String printJson = o.getPrintJson();
//            if (StringUtils.isEmpty(printJson)) {
//                d.setPrintObject(new DesignPythonItemPrint(o.getPrintPath(),
//                        CollectionLevel1TypeEnum.PRINT_BOARD.getRealName(), 0.3f, Boolean.FALSE));
//            } else {
//                d.setPrintObject(JSON.parseObject(printJson, DesignPythonItemPrint.class));
//            }
        }));
        //single 和 Models(模特)时候 系统元素为空
        List<DesignItemDetail> filterDetail2 = designItemDetails.stream()
//                        .filter(f -> SYS_HAIRSTYLE_SHOES.contains(f.getType()) )
                .filter(f -> SYS_HAIRSTYLE_SHOES_BODY.contains(f.getType()))
                .collect(Collectors.toList());
        response.setOthers(CopyUtil.copyList(filterDetail2, DesignItemOthersDetailVO.class, (o, d) -> {
            // todo 不确定businessId的作用，暂时取消传递,查看影响
//            d.setId(o.getBusinessId());
            d.setId(0L);
            d.setPath(minioUtil.getPresignedUrl(o.getPath(), 24 * 60));
            d.setMinIOPath(o.getPath());
            d.setPrintObject(new DesignPythonItemPrint());
        }));
        return editDesignItemLayer(flag, designPythonOutfit,
                minioUtil.getPresignedUrl(designPythonOutfit.getDesignUrl(), 24 * 60),
                editResponseColor(designItemDetails, response));
    }

    @Override
    public Integer designProcess(String processId) {
        ProcessIdObject object = new ProcessIdObject();
        object.setProcess_id(processId);

        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .pingInterval(5, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .build();

        MediaType mediaType = MediaType.parse("application/json");
        String param = JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect);
        log.info("designProcess请求python 参数:####{}", param);
        RequestBody body = RequestBody.create(mediaType, param);

        Request request = new Request.Builder()
                .url(accessPythonIp + ":" + accessPythonPort + "/api/get_progress")
                .method("POST", body)
                .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==")
                .addHeader("Content-Type", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                String responseBody = Objects.requireNonNull(response.body()).string();
                JSONObject responseObject = JSON.parseObject(responseBody);
                String num = responseObject.getString("data");
                return Integer.valueOf(num);
            }
        } catch (IOException | JSONException e) {
            log.error("PythonService##design进度条异常###{}", ExceptionUtil.getThrowableList(e));
        }

        return 0;
    }


    private String converTypeToLevel1(String type) {
        if (StringUtils.isEmpty(type)) {
            return null;
        }
        SysFileLevel2TypeEnum sysFileLevel2TypeEnum = SysFileLevel2TypeEnum.realNameOf(type);
        if (Objects.isNull(sysFileLevel2TypeEnum)) {
            return null;
        }
        if (OUTWEAR_DRESS_BLOUSE.contains(type) || SKIRT_TROUSERS.contains(type)) {
            return CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName();
        }
        return null;
    }

    private Design selectByCollectionId(Long collectionId) {
        QueryWrapper<Design> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("collection_id", collectionId);
        return designMapper.selectOne(queryWrapper);
    }

    private int deleteByCollectionId(Long collectionId) {
        QueryWrapper<Design> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("collection_id", collectionId);
        Design design = new Design();
        design.setCollectionId(0L);
        return designMapper.update(design, queryWrapper);
    }

    private Long saveOne(DesignCollectionDTO designDTO, Long collectionId, Long accountId) {
        Design design = CopyUtil.copyObject(designDTO, Design.class);
        design.setCreateDate(DateUtil.getByTimeZone(designDTO.getTimeZone()));
        design.setCollectionId(collectionId);
        design.setAccountId(accountId);
        if (designMapper.insert(design) <= 0) {
            throw new BusinessException("save.design.failed");
        }
        return design.getId();
    }

    /**
     * 避免多次连接数据，所这里一次查多条颜色并利用designItemDetailId保持颜色与vo的对应关系
     *
     * @param designItemDetails
     * @param designItemDetailVO
     * @return
     */
    private DesignItemDetailVO editResponseColor(List<DesignItemDetail> designItemDetails, DesignItemDetailVO designItemDetailVO) {
        // 使用designItemDetailId rgb(String)做映射
        HashMap<Long, String> designItemDetailIdColor = new HashMap<>();
        designItemDetails.forEach(designItemDetail -> {
            if (!StringUtil.isNullOrEmpty(designItemDetail.getColor())) {
                designItemDetailIdColor.put(designItemDetail.getId(), designItemDetail.getColor());
            }
        });

        if (!CollectionUtil.isEmpty(designItemDetailIdColor)){
            Map<String, PantoneVO> pantoneByRgbBatch = panToneService.getPantoneByRgbBatch(new ArrayList<>(designItemDetailIdColor.values()));
            designItemDetailVO.getClothes().forEach(c -> {
                PantoneVO pantoneVO = pantoneByRgbBatch.get(designItemDetailIdColor.get(c.getId()));
                c.setColor(pantoneVO);
            });

            designItemDetailVO.getOthers().forEach(o -> {
                PantoneVO pantoneVO = pantoneByRgbBatch.get(designItemDetailIdColor.get(o.getId()));
                o.setColor(pantoneVO);
            });
        }

        return designItemDetailVO;
    }

    private DesignItemDetailVO editDesignItemLayer(Boolean flag, TDesignPythonOutfit designPythonOutfit, String designItemUrl, DesignItemDetailVO designItemDetailVO) {
        ArrayList<DesignPythonOutfitVO> detailsVO = new ArrayList<>();

        if (flag) {
            // 1、判断designPythonOutfitId查出的图层信息是否为空（不允许为空，系统内部错误）
            List<TDesignPythonOutfitDetail> details = designPythonOutfitDetailService.getDetailByDesignPythonOutfitId(designPythonOutfit.getId());
            if (Objects.isNull(details)){
                log.error("Layer information is empty! DesignPythonOutfitId is " + designPythonOutfit.getId());
                throw new BusinessException("layer.information.not.found");
            }

            // 为没有优先级的图层添加优先级
            designPythonOutfitDetailService.setDesignPythonOutfitDetailPriority(details);

            details.forEach(detail -> {
//                List<Long> offset = new ArrayList<>();
//                if (StringUtil.isNullOrEmpty(detail.getOffset()) || detail.getOffset().equals("null")) {
//                    offset = Arrays.asList(0L, 0L);
//                } else {
//                    offset = Arrays.stream(detail.getOffset().replaceAll("\\[|\\]", "").split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
//                }
                detailsVO.add(designPythonOutfitDetailService.convertToDesignPythonOutfitVO(detail, null));
            });

            // 2、将查询出的图层信息填充到designItemDetailVO中
            designItemDetailVO.setDesignItemUrl(minioUtil.getPresignedUrl(designPythonOutfit.getDesignUrl(), 24 * 60));
            // 2.1 填充clothes
            designItemDetailVO.getClothes().forEach(c -> {
//                String type = c.getType().toLowerCase();
//                List<DesignPythonOutfitVO> outfitVOS = detailsVO.stream().filter((detail -> detail.getImageCategory().equals(type + "_back") ||
//                        detail.getImageCategory().equals(type + "_front"))).collect(Collectors.toList());
                List<DesignPythonOutfitVO> outfitVOS = detailsVO.stream().filter(detail -> detail.getPriority().equals(c.getPriority())).collect(Collectors.toList());

                c.setLayersObject(outfitVOS);
            });
            // 2.2 填充others
            designItemDetailVO.getOthers().forEach(o -> {
                String type = o.getType().toLowerCase();
                List<DesignPythonOutfitVO> outfitVOS = detailsVO.stream().filter(detail -> detail.getImageCategory().equals(type + "_back") ||
                        detail.getImageCategory().equals(type + "_front") ||
                        detail.getImageCategory().equals(type + "_left") ||
                        detail.getImageCategory().equals(type + "_right") ||
                        detail.getImageCategory().equals(type)).collect(Collectors.toList());
                o.setLayersObject(outfitVOS);
            });
        } else {
            designItemDetailVO.setDesignItemUrl(designItemUrl);
        }

        return designItemDetailVO;
    }

    private DesignSinglePrintDTO convertToDesignSinglePrintDTO(List<DesignItemDetailPrint> designItemDetailPrints) {
        DesignSinglePrintDTO designSinglePrintDTO = new DesignSinglePrintDTO();
        List<DesignSinglePrint> prints = new ArrayList<>();

        // 只有一个印花
        if (designItemDetailPrints.size() == 1) {
            DesignItemDetailPrint detailPrint = designItemDetailPrints.get(0);
            DesignSinglePrint designSinglePrint = new DesignSinglePrint();
            designSinglePrintDTO.setIfSingle(detailPrint.getSingleOrOverall().equals("single") ? Boolean.TRUE : Boolean.FALSE);
            designSinglePrint.setLocation(JSONArray.parseArray(detailPrint.getPosition(), Double.class));
            designSinglePrint.setAngle(detailPrint.getAngle());
            designSinglePrint.setPriority(detailPrint.getPriority());
            designSinglePrint.setPath(minioUtil.getPresignedUrl(detailPrint.getPath(), 24 * 60));
            designSinglePrint.setMinIOPath(detailPrint.getPath());
            designSinglePrint.setScale(detailPrint.getScale());
            prints.add(designSinglePrint);
        } else {
            // single模式下多个印花
            designSinglePrintDTO.setIfSingle(Boolean.TRUE);
            designItemDetailPrints.forEach(print -> {
                if (print.getSingleOrOverall().equals("single")) {
                    prints.add(new DesignSinglePrint(
                            minioUtil.getPresignedUrl(print.getPath(), 24 * 60),
                            print.getPath(),
                            JSONArray.parseArray(print.getPosition(), Double.class),
                            print.getScale(),
                            print.getAngle(),
                            print.getPriority()));
                }

            });
        }
        designSinglePrintDTO.setPrints(prints);
        return designSinglePrintDTO;

    }

    @Override
    public List<String> getModel(List<Long> designItemIdList){
        ArrayList<String> models = new ArrayList<>();
        List<DesignItem> designIdById = designItemService.selectDesignIdById(designItemIdList);
        if (CollectionUtil.isEmpty(designIdById)){
            log.info("according to the designItemIdList cannot find the designIdList");
            throw new BusinessException("design.not.found");
        }
        List<Long> designIdList = designIdById.stream().map(DesignItem::getDesignId).collect(Collectors.toList());
        List<Design> designs = selectList(designIdList);
        if (CollectionUtil.isEmpty(designIdList)){
            log.info("according to the designIdList cannot find the design");
            throw new BusinessException("design.not.found");
        }
        List<Long> modelFromLibIds = designs.stream().filter(design -> design.getModelType().equals("Library")).map(Design::getTemplateId).collect(Collectors.toList());
        if (!CollectionUtil.isEmpty(modelFromLibIds)){
            models.addAll(libraryService.getByIds(modelFromLibIds).stream()
                    .map(d -> minioUtil.getPresignedUrl(d.getUrl(), 24 * 60))
                    .collect(Collectors.toList()));
        }
        List<Long> modelFromSysIds = designs.stream().filter(design -> design.getModelType().equals("System")).map(Design::getTemplateId).collect(Collectors.toList());
        if (!CollectionUtil.isEmpty(modelFromSysIds)){
            models.addAll(sysFileService.getByIds(modelFromSysIds).stream()
                    .map(d -> minioUtil.getPresignedUrl(d.getUrl(), 24 * 60))
                    .collect(Collectors.toList()));
        }

        return models;
    }

    private List<Design> selectList(List<Long> designIdList){
        QueryWrapper<Design> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",designIdList);

        return designMapper.selectList(queryWrapper);
    }
}
