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.constant.CommonConstant;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.enums.*;
import com.ai.da.common.response.PageBaseResponse;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.*;
import com.ai.da.mapper.primary.*;
import com.ai.da.mapper.primary.entity.*;
import com.ai.da.model.dto.*;
import com.ai.da.model.enums.*;
import com.ai.da.model.vo.*;
import com.ai.da.python.vo.ModelPathObject;
import com.ai.da.service.*;
import com.alibaba.fastjson.JSON;
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.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ai.da.common.enums.CollectionLevel2TypeEnum.OUTWEAR;

/**
 * 服务实现类
 *
 * @author yanglei
 * @since 2022-09-30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LibraryServiceImpl extends ServiceImpl<LibraryMapper, Library> implements LibraryService {
    private final AccountMapper accountMapper;
    private final BrandRelLibraryMapper brandRelLibraryMapper;
    private final ClassificationService classificationService;
    private final DesignItemDetailService designItemDetailService;
    private final EductionLibraryMapper eductionLibraryMapper;
    private final EnterpriseLibraryMapper enterpriseLibraryMapper;
    private final FileProperties fileProperties;
    private final GenerateDetailMapper generateDetailMapper;
    private final MinioUtil minioUtil;
    private final LibraryMapper libraryMapper;
    private final LibraryCopyMapper libraryCopyMapper;
    private final LibraryModelPointMapper libraryModelPointMapper;
    private final LibraryModelPointCopyMapper libraryModelPointCopyMapper;
    private final PythonTAllInfoService pythonTAllInfoService;
    private final SysFileMapper sysFileMapper;
    private final SysFileExtraMapper sysFileExtraMapper;
    private final WorkspaceService workspaceService;

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

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

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

    private static List<String> top = Arrays.asList(CollectionLevel2TypeEnum.DRESS.getRealName(),
            OUTWEAR.getRealName(), CollectionLevel2TypeEnum.BLOUSE.getRealName());
    private static List<String> bottom = Arrays.asList(CollectionLevel2TypeEnum.SKIRT.getRealName(),
            CollectionLevel2TypeEnum.TROUSERS.getRealName());

    @Override
    public List<LibraryVo> selectByAccountIdAnd1TypeList(Long accountId, List<String> level1Types) {
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_id", accountId);
        queryWrapper.in("level1_type", level1Types);
        return CopyUtil.copyList(libraryMapper.selectList(queryWrapper), LibraryVo.class);
    }

    @Override
    public PageBaseResponse<QueryLibraryPageVO> queryLibraryPage(QueryLibraryPageServiceDTO query) {
        AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
        // 分页数据
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        if (!query.getLevel1Type().equals(LibraryLevel1TypeEnum.DESIGN_ELEMENTS.getRealName())) {
            queryWrapper.eq("account_id", authPrincipalVo.getId());
        }

        if (!StringUtils.isEmpty(query.getLevel1Type())) {
            LibraryLevel1TypeEnum level1TypeEnum = LibraryLevel1TypeEnum.uploadOf(query.getLevel1Type());
            if (Objects.isNull(level1TypeEnum)) {
                throw new BusinessException("unknown.parameter.level1Type");
            }
            queryWrapper.eq("level1_type", query.getLevel1Type());
        }
        if (!StringUtils.isEmpty(query.getModelSex()) && query.getLevel1Type().equals(LibraryLevel1TypeEnum.SKETCH_BOARD.getRealName())) {
            queryWrapper.eq("level3_type", query.getModelSex());
        }
        if (!StringUtils.isEmpty(query.getModelSex()) && query.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName())) {
            queryWrapper.eq("level2_type", query.getModelSex());
        }
        if (!StringUtils.isEmpty(query.getLevel2Type())) {
//            CollectionLevel2TypeEnum level2TypeEnum = CollectionLevel2TypeEnum.of(query.getLevel2Type());
//            if (Objects.isNull(level2TypeEnum)) {
//                throw new BusinessException("unknown.parameter.level2Type");
//            }
            queryWrapper.eq("level2_type", query.getLevel2Type());
        }
        if (!StringUtils.isEmpty(query.getType())) {
            LibraryTopTypeEnum libraryTopTypeEnum = LibraryTopTypeEnum.uploadOf(query.getType());
            Assert.notNull(libraryTopTypeEnum, "unknown type " + query.getType());
            if (libraryTopTypeEnum.equals(LibraryTopTypeEnum.PRINT)) {
                queryWrapper.eq("level1_type", LibraryLevel1TypeEnum.PRINT_BOARD.getRealName());
            } else {
                queryWrapper.eq("level1_type", LibraryLevel1TypeEnum.SKETCH_BOARD.getRealName());
                if (LibraryTopTypeEnum.TOP.equals(libraryTopTypeEnum)) {
                    queryWrapper.in("level2_type", top);
                } else {
                    queryWrapper.in("level2_type", bottom);
                }
            }
        }
        if (!StringUtils.isEmpty(query.getPictureName())) {
            queryWrapper.like("name", query.getPictureName());
        }

        if (!StringUtils.isEmpty(query.getAgeGroup())) {
//            queryWrapper.eq("level3_type", query.getAgeGroup());
//            queryWrapper.eq("age_group", query.getAgeGroup());
            queryWrapper.lambda().and(wrapper -> wrapper
                            .eq(Library::getLevel3Type, query.getAgeGroup())
                            .or()
                            .eq(Library::getAgeGroup, query.getAgeGroup())
                    );
        }

        if (query.getBrandId() != null) {
            QueryWrapper<BrandRelLibrary> qw = new QueryWrapper<>();
            qw.lambda().eq(BrandRelLibrary::getBrandId, query.getBrandId());
            Set<Long> collect = brandRelLibraryMapper.selectList(qw).stream().map(BrandRelLibrary::getLibraryId).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(collect)) {
                queryWrapper.in("id", collect);
            }else {
                return PageBaseResponse.success(new Page<>());
            }
        }

        // 新增分类过滤
        if (CollectionUtil.isNotEmpty(query.getClassificationIdList())) {
            List<Long> libraryIdList = new ArrayList<>();
            if (query.getIntersection() == 0) {
                for (Long classificationId : query.getClassificationIdList()) {
                    libraryIdList.addAll(classificationService.getLibraryIdListByClassificationId(classificationId));
                }
                if (CollectionUtil.isNotEmpty(libraryIdList)) {
                    queryWrapper.lambda().in(Library::getId, libraryIdList);
                }else {
                    return PageBaseResponse.success(new Page<>());
                }
            }else {
                for (int i = 0; i < query.getClassificationIdList().size(); i++) {
                    List<Long> libraryIdListByClassificationId = classificationService.getLibraryIdListByClassificationId(query.getClassificationIdList().get(i));
                    if (i == 0) {
                        libraryIdList.addAll(libraryIdListByClassificationId);
                    }else {
                        libraryIdList.retainAll(libraryIdListByClassificationId);
                    }
                    if (CollectionUtil.isEmpty(libraryIdList)) {
                        return PageBaseResponse.success(new Page<>());
                    }
                }
                queryWrapper.lambda().in(Library::getId, libraryIdList);
            }
        }
        queryWrapper.orderByDesc("id");
        // 1. 先查询所有符合条件的 Library 数据
        List<Library> libraryList = getBaseMapper().selectList(queryWrapper);
        if (CollectionUtils.isEmpty(libraryList)) {
            return PageBaseResponse.success(new Page<>());
        }

        // 2. 封装打点内容
        Map<Long, LibraryModelPointVO> map = null;
        boolean isExist = libraryList.stream()
                .anyMatch(library -> library.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName()));
        if (isExist) {
            List<Long> libraryIds = libraryList.stream()
                    .filter(library -> library.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName()))
                    .map(Library::getId)
                    .collect(Collectors.toList());
            List<LibraryModelPointVO> libraryModelPointVOS = selectByLibraryIds(libraryIds);
            if (!CollectionUtils.isEmpty(libraryModelPointVOS)) {
                map = libraryModelPointVOS.stream()
                        .collect(Collectors.toMap(LibraryModelPointVO::getRelationId, v -> v));
            }
        }
        Map<Long, LibraryModelPointVO> finalMap = map;

        // 3. 转换 Library 为 QueryLibraryPageVO，并通过 minioUtil 过滤掉不存在的 URL
        List<QueryLibraryPageVO> convertedList = libraryList.stream()
                .map(library -> {
                    QueryLibraryPageVO libraryPageVO = CopyUtil.copyObject(library, QueryLibraryPageVO.class);
                    libraryPageVO.setDesignType(DesignTypeEnum.LIBRARY.getRealName());
                    libraryPageVO.setMinIOPath(library.getUrl());
                    String url = library.getUrl();
                    if (minioUtil.doesObjectExist(url)) {
                        libraryPageVO.setUrl(minioUtil.getPreSignedUrl(url, 24 * 60));
                        if (finalMap != null && finalMap.containsKey(library.getId())) {
                            libraryPageVO.setLibraryModelPoint(finalMap.get(library.getId()));
                        }
                        if (libraryPageVO.getLevel1Type().equals(LibraryLevel1TypeEnum.SKETCH_BOARD.getRealName())) {
                            if (!StringUtils.isEmpty(libraryPageVO.getLevel2Type())) {
                                Position position = Position.getPosition(libraryPageVO.getLevel2Type());
                                libraryPageVO.setLevel2TypeEnum(new BizJson(
                                        position.getValue(),
                                        position.name(),
                                        BusinessException.getMessageFromResource(position.name()))
                                );
                            }
                        }
                        if (libraryPageVO.getLevel1Type().equals(LibraryLevel1TypeEnum.PRINT_BOARD.getRealName())) {
                            PrintboardLevel2TypeEnum printboardLevel2TypeEnum = PrintboardLevel2TypeEnum.fromName(libraryPageVO.getLevel2Type());
                            libraryPageVO.setLevel2TypeEnum(new BizJson(
                                    printboardLevel2TypeEnum.getValue(),
                                    printboardLevel2TypeEnum.name(),
                                    BusinessException.getMessageFromResource(printboardLevel2TypeEnum.name()))
                            );
                        }
                        if (libraryPageVO.getLevel1Type().equals(LibraryLevel1TypeEnum.DESIGN_ELEMENTS.getRealName())) {
                            DesignElementsEnum designElementsEnum = DesignElementsEnum.fromName(libraryPageVO.getLevel2Type());
                            libraryPageVO.setLevel2TypeEnum(new BizJson(
                                    designElementsEnum.getValue(),
                                    designElementsEnum.name(),
                                    BusinessException.getMessageFromResource(designElementsEnum.name()))
                            );
                        }
                        return libraryPageVO;
                    } else {
                        // 如果对应的 MinIO 文件不存在，则返回 null，后续过滤掉
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 4. 手动分页
        int total = convertedList.size();
        int currentPage = query.getPage();    // 当前页码（从1开始）
        int pageSize = query.getSize();         // 每页大小
        int fromIndex = (currentPage - 1) * pageSize;
        int toIndex = Math.min(total, currentPage * pageSize);
        List<QueryLibraryPageVO> pageList = new ArrayList<>();
        if (fromIndex < total) {
            pageList = convertedList.subList(fromIndex, toIndex);
        }

        // 5. 构造 IPage 对象（使用 MyBatis-Plus 的 Page 实现）
        IPage<QueryLibraryPageVO> pageResult = new Page<>(currentPage, pageSize, total);
        pageResult.setRecords(pageList);

        // 6. 返回结果
        return PageBaseResponse.success(pageResult);
    }

    public List<LibraryModelPointVO> selectByLibraryIds(List<Long> libraryIds) {
        QueryWrapper<LibraryModelPoint> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LibraryModelPoint::getModelType, ModelType.LIBRARY.getValue());
        queryWrapper.in("relation_id", libraryIds);
        List<LibraryModelPoint> libraryModelPoints = libraryModelPointMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(libraryModelPoints)) {
            return null;
        }
        return CopyUtil.copyList(libraryModelPoints, LibraryModelPointVO.class, (o, d) -> {
            d.setTemplateId(o.getId());
            d.setHandLeft(JSON.parseObject(o.getHandLeft(), List.class));
            d.setHandRight(JSON.parseObject(o.getHandRight(), List.class));
            d.setShoulderRight(JSON.parseObject(o.getShoulderRight(), List.class));
            d.setShoulderLeft(JSON.parseObject(o.getShoulderLeft(), List.class));
            d.setWaistbandRight(JSON.parseObject(o.getWaistbandRight(), List.class));
            d.setWaistbandLeft(JSON.parseObject(o.getWaistbandLeft(), List.class));
        });
    }

    @Override
    public LibraryUpdateVo upload(LibraryUploadDTO libraryUploadDTO) {
        //用户信息
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
        LibraryLevel1TypeEnum level1TypeEnum = LibraryLevel1TypeEnum.uploadOf(libraryUploadDTO.getLevel1Type());
        if (Objects.isNull(level1TypeEnum)) {
            throw new BusinessException("unknown.parameter.level1Type");
        }
//        if (!StringUtils.isEmpty(libraryUploadDTO.getLevel2Type())) {
//            CollectionLevel2TypeEnum level2TypeEnum = CollectionLevel2TypeEnum.of(libraryUploadDTO.getLevel2Type());
//            if (Objects.isNull(level2TypeEnum)) {
//                throw new BusinessException("unknown.parameter.level2Type");
//            }
//        }
        if ((level1TypeEnum.equals(LibraryLevel1TypeEnum.SKETCH_BOARD) || level1TypeEnum.equals(LibraryLevel1TypeEnum.PRINT_BOARD) || level1TypeEnum.equals(LibraryLevel1TypeEnum.DESIGN_ELEMENTS)) && StringUtils.isEmpty(libraryUploadDTO.getLevel2Type())) {
            throw new BusinessException("level2Type.cannot.be.empty");
        }
        String path = calculateFileUrl(level1TypeEnum, libraryUploadDTO.getLevel2Type(), libraryUploadDTO.getModelSex(), userInfo.getId());
        String bucketName = null;
        switch (level1TypeEnum) {
            case MODELS:
            case MOOD_BOARD:
            case PRINT_BOARD:
            case SKETCH_BOARD:
            case DESIGN_ELEMENTS:
                bucketName = users;
                break;
            case MARKETING_SKETCH:
                // 走不到
                throw new BusinessException("MARKETING_SKETCH.type.have.been.removed");
            default:
                throw new BusinessException("unknown.level1TypeEnum");
        }
        //保存element元素
        if (!StringUtils.isEmpty(libraryUploadDTO.getModelType())) {
            if (libraryUploadDTO.getModelType().equals(ModelType.LIBRARY.getValue())) {
                String filePath = minioUtil.upload(bucketName, path, libraryUploadDTO.getFile());
                String newFilePath = processMannequins(filePath);
                Library library = resolveData(libraryUploadDTO, userInfo, newFilePath);
                LibraryUpdateVo libraryUpdateVo = CopyUtil.copyObject(library, LibraryUpdateVo.class);
                libraryUpdateVo.setMinIOPath(libraryUpdateVo.getUrl());
                libraryUpdateVo.setUrl(minioUtil.getPreSignedUrl(newFilePath, 24 * 60));
                libraryUpdateVo.setCheckMd5(Boolean.TRUE);
                return libraryUpdateVo;
            } else if (libraryUploadDTO.getModelType().equals(ModelType.SYSTEM.getValue())) {
                bucketName = sysImage;
                path = "models/" + libraryUploadDTO.getModelSex().toLowerCase();
                String filePath = minioUtil.upload(bucketName, path, libraryUploadDTO.getFile());
                String newFilePath = processMannequins(filePath);
//                String newFilePath = filePath;
                Library library = resolveData(libraryUploadDTO, userInfo, newFilePath);
                LibraryUpdateVo libraryUpdateVo = CopyUtil.copyObject(library, LibraryUpdateVo.class);
                libraryUpdateVo.setMinIOPath(libraryUpdateVo.getUrl());
                libraryUpdateVo.setUrl(minioUtil.getPreSignedUrl(newFilePath, 24 * 60));
                libraryUpdateVo.setCheckMd5(Boolean.TRUE);
                return libraryUpdateVo;
            } else {
                throw new BusinessException("unknown.modelType");
            }
        } else {
            String filePath = minioUtil.upload(bucketName, path, libraryUploadDTO.getFile());
            if (libraryUploadDTO.getLevel1Type().equals(LibraryLevel1TypeEnum.SKETCH_BOARD.getRealName())) {
                processSketchBoards(filePath, libraryUploadDTO.getLevel2Type());
            }
            //保存element元素
            Library library = resolveData(libraryUploadDTO, userInfo, filePath);
            LibraryUpdateVo libraryUpdateVo = CopyUtil.copyObject(library, LibraryUpdateVo.class);
            libraryUpdateVo.setMinIOPath(libraryUpdateVo.getUrl());
            libraryUpdateVo.setUrl(minioUtil.getPreSignedUrl(libraryUpdateVo.getUrl(), 24 * 60));
            libraryUpdateVo.setCheckMd5(Boolean.TRUE);
            return libraryUpdateVo;
        }
    }

    @Override
    public String processMannequins(String filePath) {
        ModelPathObject modelPathObject = new ModelPathObject();
        modelPathObject.setModel_path(filePath);
        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒)
                .readTimeout(60, TimeUnit.SECONDS)//读取超时(单位:秒)
                .writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒)
                .build();
        MediaType mediaType = MediaType.parse("application/json");
        //关闭FastJson的引用检测 防止出现$ref 现象
        String param = JSON.toJSONString(modelPathObject, SerializerFeature.DisableCircularReferenceDetect);
        log.info("processMannequins请求python 参数:####{}", param);
        RequestBody body = RequestBody.create(mediaType, param);
        Request request = new Request.Builder()
                .url(accessPythonIp + ":" + accessPythonPort + "/api/model_process")
//                .url(accessPythonIp + ":10200/aifda/api/v1.0/generate")
                .method("POST", body)
//                .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==")
                .addHeader("Content-Type", "application/json")
                .build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException ioException) {
            log.error("PythonService##processMannequins异常###{}", ExceptionUtil.getThrowableList(ioException));
            throw new BusinessException("processMannequins.interface.exception");
        }
        //去除限流
//        AccessLimitUtils.validateOut("design");
        if (response.isSuccessful()) {
            try {
                if (Objects.isNull(response.body())) {
                    throw new BusinessException("processMannequins.interface.exception");
                }
                String responseBody = response.body().string();
                JSONObject responseObject = JSON.parseObject(responseBody);
                String newMinioPath = responseObject.getString("data");
                return newMinioPath;
            } catch (IOException | JSONException e) {
                log.error(e.getMessage());
                throw new BusinessException("processMannequins.interface.exception");
            }
        }
        //生成失败
        throw new BusinessException("processMannequins.interface.exception");
    }

    /**
     * 去sketch白边
     * @param filePath
     * @param category
     */
    @Override
    public void processSketchBoards(String filePath, String category) {
        Long imageId = pythonTAllInfoService.getImageIdByPath(filePath);
        SketchesBoundingBox sketchesBoundingBox = new SketchesBoundingBox();
        List<Sketches> list = new ArrayList<>();
        Sketches sketches = new Sketches();
        sketches.setImage_id(String.valueOf(imageId));
        sketches.setImage_url(filePath);
        sketches.setImage_category(category);
        list.add(sketches);
        sketchesBoundingBox.setSketches(list);

        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒)
                .readTimeout(60, TimeUnit.SECONDS)//读取超时(单位:秒)
                .writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒)
                .build();
        MediaType mediaType = MediaType.parse("application/json");
        //关闭FastJson的引用检测 防止出现$ref 现象
        String param = JSON.toJSONString(sketchesBoundingBox, SerializerFeature.DisableCircularReferenceDetect);
        log.info("processSketchBoards请求python 参数:####{}", param);
        RequestBody body = RequestBody.create(mediaType, param);
        Request request = new Request.Builder()
//                .url(accessPythonIp + ":" + accessPythonPort + "/api/design_pre_processing")
                .url(fastApiPythonAddress + "/api/design_pre_processing")
                .method("POST", body)
//                .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==")
                .addHeader("Content-Type", "application/json")
                .build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException ioException) {
            log.error("PythonService##processSketchBoards异常###{}", ExceptionUtil.getThrowableList(ioException));
            throw new BusinessException("processSketchBoards.interface.exception");
        }
        //去除限流
//        AccessLimitUtils.validateOut("design");
        if (response.isSuccessful()) {
            try {
                if (Objects.isNull(response.body())) {
                    throw new BusinessException("processSketchBoards.interface.exception");
                }
                String responseBody = response.body().string();
                JSONObject responseObject = JSON.parseObject(responseBody);
                return;
//                String newMinioPath = responseObject.getString("data");
//                return newMinioPath;
            } catch (IOException | JSONException e) {
                log.error(e.getMessage());
                throw new BusinessException("processSketchBoards.interface.exception");
            }
        }
        //生成失败
        throw new BusinessException("processSketchBoards.interface.exception");
    }

    @Override
    public Boolean checkMd5(String level1Type, String level2Type, String sex, String md5) {
        AuthPrincipalVo userInfo = UserContext.getUserHolder();
        QueryWrapper<Library> qw = new QueryWrapper<>();
        qw.lambda().eq(Library::getAccountId, userInfo.getId());
        qw.lambda().eq(Library::getLevel1Type, level1Type);
        if (!StringUtils.isEmpty(sex)) {
            if (level1Type.equals(LibraryLevel1TypeEnum.SKETCH_BOARD.getRealName())) {
                qw.lambda().eq(Library::getLevel2Type, level2Type);
                qw.lambda().eq(Library::getLevel3Type, sex);
            } else {
//                qw.lambda().eq(Library::getLevel2Type, sex);
                qw.lambda().eq(Library::getLevel3Type, sex);
            }
        }
        qw.lambda().eq(Library::getMd5, md5);
        List<Library> libraryList = libraryMapper.selectList(qw);
        if (!CollectionUtils.isEmpty(libraryList)) {
//            throw new BusinessException("Your library already contains the images you uploaded, Are you sure to upload them");
            return Boolean.FALSE;
        } else {
            return Boolean.TRUE;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteLibrary(LibraryDeleteDTO deleteDTO) {
        List<Library> librarys = libraryMapper.selectBatchIds(deleteDTO.getLibraryIds());
        if (CollectionUtils.isEmpty(librarys)) {
            throw new BusinessException("libraryList.not.found");
        }
        List<Long> femaleModelIds = librarys.stream()
                .filter(o -> o.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName()) && o.getLevel2Type().equals(Sex.FEMALE.getValue()))
                .map(Library::getId)
                .collect(Collectors.toList());
        List<Long> maleModelIds = librarys.stream()
                .filter(o -> o.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName()) && o.getLevel2Type().equals(Sex.MALE.getValue()))
                .map(Library::getId)
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(femaleModelIds)) {
            // 检测模特是否被工作空间引用
            checkModel(Sex.FEMALE.getValue(), femaleModelIds, deleteDTO.getDeleteModelConfirm());
        }
        if (CollectionUtil.isNotEmpty(maleModelIds)) {
            checkModel(Sex.MALE.getValue(), maleModelIds, deleteDTO.getDeleteModelConfirm());
        }
        libraryMapper.deleteBatchIds(deleteDTO.getLibraryIds());

        // 1、确定该libraryId是否被generateDetail引用
        List<GenerateDetail> generateDetails = selectBatchByLibraryId(deleteDTO.getLibraryIds());

        // 2、有，则更新generateDetail表的is_like字段和library_id字段
        if (!generateDetails.isEmpty()){
            updateLikeStatusBatch(
                    generateDetails.stream().map(GenerateDetail::getId).collect(Collectors.toList()),
                    (byte)0,
                    0L,
                    deleteDTO.getTimeZone()
            );
        }

        // 判断当前libraryId是否被brand_rel_library引用
        QueryWrapper<BrandRelLibrary> brandRelLibraryQueryWrapper = new QueryWrapper<>();
        brandRelLibraryQueryWrapper.lambda().in(BrandRelLibrary::getLibraryId, deleteDTO.getLibraryIds());

        brandRelLibraryMapper.delete(brandRelLibraryQueryWrapper);
//        for (Library library : librarys) {
//            if (library.getUrl().startsWith(sysImage)) {
//                continue;
//            }
//            minioUtil.deleteObject(library.getUrl());
//        }

    }

    public List<GenerateDetail> selectBatchByLibraryId(List<Long> libraryId) {
        QueryWrapper<GenerateDetail> qw = new QueryWrapper<>();
        qw.in("library_id", libraryId);

        return generateDetailMapper.selectList(qw);
    }

    public void updateLikeStatusBatch(List<Long> generateDetailIdList, Byte hasLike, Long libraryId, String timeZone) {
        QueryWrapper<GenerateDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", generateDetailIdList);

        GenerateDetail generateDetail = new GenerateDetail();
        generateDetail.setIsLike(hasLike);
        generateDetail.setLibraryId(libraryId);
        generateDetail.setUpdateDate(DateUtil.getByTimeZone(timeZone));

        generateDetailMapper.update(generateDetail, queryWrapper);
    }

    @Override
    public void deleteTrialData(Long userId) {
        QueryWrapper<Library> qw = new QueryWrapper<>();
        qw.lambda().eq(Library::getAccountId, userId);
        libraryMapper.delete(qw);
    }

    @Override
    public void moveLibraryDate() throws ParseException {
        QueryWrapper<LibraryCopy> qw = new QueryWrapper<>();
        // 定义日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 定义日期字符串
        String dateString = "2023-09-01 00:00:00";
        qw.gt("create_date", dateFormat.parse(dateString));
        // 生产所有数据
        List<LibraryCopy> libraryList = libraryCopyMapper.selectList(qw);
        for (LibraryCopy libraryCopy : libraryList) {
            QueryWrapper<Library> one = new QueryWrapper<>();
            one.lambda().eq(Library::getAccountId, libraryCopy.getAccountId());
            one.lambda().eq(Library::getMd5, libraryCopy.getMd5());
            List<Library> libraryList1 = libraryMapper.selectList(one);
            if (CollectionUtil.isNotEmpty(libraryList1)) {
                continue;
            }
            String url = libraryCopy.getUrl();
            if (StringUtils.isEmpty(url)) {
                continue;
            }
            if (url.contains("/download/")) {
                String[] downloads = url.split("/download/");
                if (downloads.length == 2) {
                    String linux = downloads[1];
                    String windows = linux.replaceAll("/", "\\\\");
                    String path = "C:\\workspace\\fileData\\file\\" + windows;
                    File file = FileUtil.getFile(path);
                    if (file != null) {
                        String name = file.getName();
                        System.out.println(name);
                        StringBuilder sb = new StringBuilder();
                        sb.append(libraryCopy.getAccountId()).append("/").append(libraryCopy.getLevel1Type().toLowerCase()).append("/");
                        if (libraryCopy.getLevel1Type().equals("Sketchboard") || libraryCopy.getLevel1Type().equals("Models")) {
                            sb.append("female/");
                        }
                        if (!StringUtils.isEmpty(libraryCopy.getLevel2Type())) {
                            sb.append(libraryCopy.getLevel2Type().toLowerCase()).append("/");
                        }
                        sb.append(name);
                        String bucketName = users;
                        boolean b = minioUtil.doesObjectExist(bucketName, sb.toString());
                        if (!b) {
                            FileItem a = getMultipartFile(file, file.getName());
                            MultipartFile multipartFile = new CommonsMultipartFile(a);
                            String upload = minioUtil.upload(bucketName, sb.toString(), multipartFile, "");
                            Library newInsert = CopyUtil.copyObject(libraryCopy, Library.class);
                            newInsert.setId(null);
                            if (libraryCopy.getLevel1Type().equals("Models")) {
                                newInsert.setLevel2Type("Female");
                                QueryWrapper<LibraryModelPointCopy> modelCopy = new QueryWrapper<>();
                                modelCopy.lambda().eq(LibraryModelPointCopy::getLibraryId, libraryCopy.getId());
                                LibraryModelPointCopy libraryModelPointCopy = libraryModelPointCopyMapper.selectOne(modelCopy);
                                LibraryModelPoint libraryModelPoint = CopyUtil.copyObject(libraryModelPointCopy, LibraryModelPoint.class);
                                libraryModelPoint.setModelType("Library");

                                upload = processMannequins(upload);
                                newInsert.setUrl(upload);
                                libraryMapper.insert(newInsert);

                                libraryModelPoint.setRelationId(newInsert.getId());
                                libraryModelPoint.setId(null);
//                                libraryModelPointService.saveOrUpdate(libraryModelPoint);
                                libraryModelPointMapper.insert(libraryModelPoint);
                                continue;
                            }
                            if (libraryCopy.getLevel1Type().equals("Sketchboard")) {
                                newInsert.setLevel3Type("Female");
                            }
                            newInsert.setUrl(upload);
                            libraryMapper.insert(newInsert);
                        }
                    }
                }
            }
        }
    }
    private static FileItem getMultipartFile(File file, String fieldName) {
        // 使用 DiskFileItemFactory 创建一个 FileItemFactory
        FileItemFactory factory = new DiskFileItemFactory(16, null);

        // 使用 FileItemFactory 创建一个 FileItem 对象
        String mimeType = getMimeType(file);
        FileItem item = factory.createItem(fieldName, mimeType, true, file.getName());

        byte[] buffer = new byte[8192];
        int bytesRead;

        try (FileInputStream fis = new FileInputStream(file);
             OutputStream os = item.getOutputStream()) {
            // 从文件中读取数据并写入 FileItem
            while ((bytesRead = fis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return item;
    }

    private static String getMimeType(File file) {
        try {
            return Files.probeContentType(file.toPath());
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    @Override
    public void checkModel(String value, List<Long> modelIds, Integer deleteModelConfirm) {
        AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
        QueryWrapper<Workspace> qw = new QueryWrapper<>();
        qw.lambda().eq(Workspace::getAccountId, authPrincipalVo.getId());
        if (value.equals(Sex.FEMALE.getValue())) {
            qw.lambda().in(Workspace::getMannequinFemaleId, modelIds);
        }
        if (value.equals(Sex.MALE.getValue())) {
            qw.lambda().in(Workspace::getMannequinMaleId, modelIds);
        }
        // TODO:isDeleted设置
        qw.lambda().eq(Workspace::getIsDeleted, 0L);
        List<Workspace> workspaceList = workspaceService.list(qw);
        if (CollectionUtil.isNotEmpty(workspaceList)) {
            if (deleteModelConfirm.equals(0)) {
                throw new BusinessException("the.model.has.been.referenced.by.the.workspace", ResultEnum.WARNING.getCode());
            }
            if (value.equals(Sex.FEMALE.getValue())) {
                QueryWrapper<SysFile> systemFemaleQw = new QueryWrapper<>();
                systemFemaleQw.lambda().eq(SysFile::getLevel1Type, "Models");
                systemFemaleQw.lambda().eq(SysFile::getLevel2Type, "Female");
                List<SysFile> sysFemaleFiles = sysFileMapper.selectList(systemFemaleQw);
                if (!CollectionUtils.isEmpty(sysFemaleFiles)) {
                    for (Workspace workspace : workspaceList) {
                        workspace.setMannequinFemaleId(sysFemaleFiles.get(0).getId());
                        workspace.setMannequinFemaleType(MannequinType.SYSTEM.getValue());
                    }
                    workspaceService.updateBatchById(workspaceList);
                }
            }
            if (value.equals(Sex.MALE.getValue())) {
                QueryWrapper<SysFile> systemMaleQw = new QueryWrapper<>();
                systemMaleQw.lambda().eq(SysFile::getLevel1Type, "Models");
                systemMaleQw.lambda().eq(SysFile::getLevel2Type, "Male");
                List<SysFile> sysMaleFiles = sysFileMapper.selectList(systemMaleQw);
                if (!CollectionUtils.isEmpty(sysMaleFiles)) {
                    for (Workspace workspace : workspaceList) {
                        workspace.setMannequinMaleId(sysMaleFiles.get(0).getId());
                        workspace.setMannequinMaleType(MannequinType.SYSTEM.getValue());
                    }
                    workspaceService.updateBatchById(workspaceList);
                }
            }
        }

    }

    private Library resolveData(LibraryUploadDTO uploadDTO, AuthPrincipalVo userInfo, String filePath) {
        if (StringUtils.isEmpty(uploadDTO.getModelType()) || uploadDTO.getModelType().equals(ModelType.LIBRARY.getValue())) {
            Library library = CopyUtil.copyObject(uploadDTO, Library.class);
            library.setAccountId(userInfo.getId());
            String originalFilename = uploadDTO.getFile().getOriginalFilename();
            if (!StringUtils.isEmpty(originalFilename)) {
                if (originalFilename.contains(".")) {
                    String name = originalFilename.substring(0,originalFilename.lastIndexOf("."));
                    library.setName(name);
//                    library.setName(originalFilename.split("\\.")[0]);
                }else {
                    library.setName(originalFilename);
                }
            }else {
                library.setName(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            library.setUrl(filePath);
            //按时区计算
            library.setCreateDate(DateUtil.getByTimeZone(uploadDTO.getTimeZone()));
            if (uploadDTO.getModelType().equals(ModelType.LIBRARY.getValue())) {
                library.setLevel2Type(uploadDTO.getModelSex());
//                library.setLevel3Type(uploadDTO.getAgeGroup());
            } else {
                library.setLevel3Type(uploadDTO.getModelSex());
            }
            if (uploadDTO.getLevel1Type().equals(LibraryLevel1TypeEnum.SKETCH_BOARD.getRealName())&&StringUtils.isEmpty(uploadDTO.getAgeGroup())) {
                log.error("前端未传ageGroup");
                library.setAgeGroup("Adult");
            } else {
                library.setAgeGroup(uploadDTO.getAgeGroup());
            }
            libraryMapper.insert(library);
            return library;
        } else if (uploadDTO.getModelType().equals(ModelType.SYSTEM.getValue())) {
            SysFile sysFile = new SysFile();
            String originalFilename = uploadDTO.getFile().getOriginalFilename();
            if (!StringUtils.isEmpty(originalFilename)) {
                if (originalFilename.contains(".")) {
                    String name = originalFilename.substring(0,originalFilename.lastIndexOf("."));
                    sysFile.setName(name);
//                    sysFile.setName(originalFilename.split("\\.")[0]);
                }else {
                    sysFile.setName(originalFilename);
                }
            }else {
                sysFile.setName(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            sysFile.setLevel1Type("Models");
            sysFile.setLevel2Type(uploadDTO.getModelSex());
            sysFile.setUrl(filePath);
            sysFile.setMd5(uploadDTO.getMd5());
            sysFile.setCreateDate(new Date());
            sysFileMapper.insert(sysFile);

            SysFileExtra extra = new SysFileExtra();
            extra.setSysId(sysFile.getId());
            extra.setAgeGroup(uploadDTO.getAgeGroup());
            sysFileExtraMapper.insert(extra);

            Library library = new Library();
            library.setId(sysFile.getId());
            library.setUrl(sysFile.getUrl());
            return library;
        } else {
            throw new BusinessException("unknown.modelType");
        }
    }

    private String calculateFileUrl(LibraryLevel1TypeEnum level1TypeEnum, String level2Type, String modelSex, Long userId) {
        if (StringUtils.isEmpty(modelSex)) {
            return StringUtils.isEmpty(level2Type) ? userId + "/" + level1TypeEnum.getRealName().toLowerCase() : userId + "/" + level1TypeEnum.getRealName().toLowerCase() + "/" + level2Type;
        } else {
            return StringUtils.isEmpty(level2Type) ? userId + "/" + level1TypeEnum.getRealName().toLowerCase() + "/" + modelSex.toLowerCase() : userId + "/" + level1TypeEnum.getRealName().toLowerCase() + "/" + modelSex.toLowerCase() + "/" + level2Type;
        }
    }

    @Override
    public void updateLibraryName(LibraryUpdateDTO libraryUpdateDTO) {
        List<Library> librarys = getByIds(libraryUpdateDTO.getLibraryIds());
        if (CollectionUtils.isEmpty(librarys)) {
            throw new BusinessException("libraryList.not.found");
        }
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", libraryUpdateDTO.getLibraryIds());
        Library library1 = new Library();
        library1.setName(libraryUpdateDTO.getLibraryName());
        library1.setUpdateDate(DateUtil.getByTimeZone(libraryUpdateDTO.getTimeZone()));
        libraryMapper.update(library1, queryWrapper);
    }

    @Override
    public List<Library> getByIds(List<Long> ids) {
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", ids);
        return libraryMapper.selectList(queryWrapper);
    }

    @Override
    public List<Library> getByMD5List(List<String> md5List) {
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("md5", md5List);
        return libraryMapper.selectList(queryWrapper);
    }

    @Override
    public List<LibraryVo> getByUrlList(List<String> urlList, Long userId) {
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("url", urlList);
        queryWrapper.in("account_id", userId);
        return CopyUtil.copyList(libraryMapper.selectList(queryWrapper), LibraryVo.class);
    }

    @Override
    public Boolean updateLibraryLevel2Type(LibraryLevel2TypeUpdateDTO libraryLevel2TypeUpdateDTO) {
        Library library = new Library();
        library.setLevel2Type(libraryLevel2TypeUpdateDTO.getLevel2Type());
        QueryWrapper<Library> qw = new QueryWrapper<>();
        qw.lambda().in(Library::getId, libraryLevel2TypeUpdateDTO.getLibraryId());
        return libraryMapper.update(library, qw) == 1;
    }

    private Library selectById(Long id) {
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        return libraryMapper.selectOne(queryWrapper);
    }

    private Boolean exists(Long id) {
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        return libraryMapper.exists(queryWrapper);
    }

    private boolean saveOne(Library library) {
        if (libraryMapper.insert(library) <= 0) {
            throw new BusinessException("save.library.failed");
        }
        return Boolean.TRUE;
    }

    @Override
    public Map<String, String> addSysModelToLib(long sysModelId) {
        Long accountId = UserContext.getUserHolder().getId();
        SysFile sysFile = sysFileMapper.selectById(sysModelId);
        if (Objects.isNull(sysFile)) {
            throw new BusinessException("model.not.found", ResultEnum.PROMPT.getCode());
        }
        SysFileExtra sysFileExtra = sysFileExtraMapper.selectOne(new QueryWrapper<SysFileExtra>().eq("sys_id", sysFile.getId()));

        // 添加模特信息到library
        Library library = CopyUtil.copyObject(sysFile, Library.class);
        library.setId(null);
        library.setAccountId(accountId);
        library.setAgeGroup(sysFileExtra.getAgeGroup());
        library.setName(DateUtil.dateToStr(new Date(), DateUtil.YYYY_MM_DD));
        List<Integer> imagesWidthAndHeight = minioUtil.getImagesWidthAndHeight(sysFile.getUrl());
        library.setWidth(imagesWidthAndHeight.get(0));
        library.setHigh(imagesWidthAndHeight.get(1));
        library.setCreateDate(new Date());
        library.setUpdateDate(null);
        libraryMapper.insert(library);

        // 添加点位信息到library
        LibraryModelPoint sysModelPoint = getByRelationId(sysModelId, "System");
        sysModelPoint.setId(null);
        sysModelPoint.setModelType("Library");
        sysModelPoint.setRelationId(library.getId());
        sysModelPoint.setCreateDate(new Date());
        libraryModelPointMapper.insert(sysModelPoint);

        Map<String, String> resp = new HashMap<>();
        resp.put("id", library.getId().toString());
        resp.put("url", minioUtil.getPreSignedUrl(library.getUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
        return resp;
    }

    public LibraryModelPoint getByRelationId(Long relationId, String modelType) {
        QueryWrapper<LibraryModelPoint> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LibraryModelPoint::getRelationId, relationId)
                .eq(LibraryModelPoint::getModelType, modelType)
                .last("limit 1");
        List<LibraryModelPoint> libraryModelPoints = libraryModelPointMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(libraryModelPoints)) {
            throw new BusinessException("modelPoint.not.found");
        }
        return libraryModelPoints.get(0);
    }


    public boolean saveToOrganizationLibrary(Long libraryId){
        // 1、判断该用户是否属于某个组织
        Long accountId = UserContext.getUserHolder().getId();
        Account account = accountMapper.selectById(accountId);
        if (Objects.nonNull(account.getOrganizationId())){
            // 2、添加元素信息到对应的住址表里
            switch(account.getSystemUser()){
                case 5:
                case 6:
                    EnterpriseLibrary enterpriseLibrary = enterpriseLibraryMapper.selectOne(new QueryWrapper<EnterpriseLibrary>().eq("library_id", libraryId));
                    if (Objects.nonNull(enterpriseLibrary)){
                        throw new BusinessException("element.already.exists");
                    }
                    // 存储到企业表
                    enterpriseLibrary = new EnterpriseLibrary();
                    enterpriseLibrary.setEnterpriseId(account.getOrganizationId());
                    enterpriseLibrary.setLibraryId(libraryId);
                    enterpriseLibrary.setCreateTime(LocalDateTime.now());
                    enterpriseLibraryMapper.insert(enterpriseLibrary);
                    log.info("企业用户添加元素到公共库");
                    return true;
                case 7:
                case 8:
                    EducationLibrary educationLibrary = eductionLibraryMapper.selectOne(new QueryWrapper<EducationLibrary>().eq("library_id", libraryId));
                    if (Objects.nonNull(educationLibrary)){
                        throw new BusinessException("element.already.exists");
                    }
                    // 存储到教育表
                    educationLibrary = new EducationLibrary();
                    educationLibrary.setEducationId(account.getOrganizationId());
                    educationLibrary.setLibraryId(libraryId);
                    educationLibrary.setCreateTime(LocalDateTime.now());
                    eductionLibraryMapper.insert(educationLibrary);
                    log.info("教育版用户添加元素到公共库");
                    return true;
                default:
                    return false;
            }
        }
        return false;
    }

    // 删除公共库中的元素
    public void deleteFromPublicLib(Long libraryId){
        // 谁有权限删除公共库里的东西？1、元素所有者  2、管理员
        Long accountId = UserContext.getUserHolder().getId();
        Account account = accountMapper.selectById(accountId);
        Library library = libraryMapper.selectById(libraryId);

        if (account.getSystemUser().equals(5)
                || account.getSystemUser().equals(7)
                || library.getAccountId().equals(accountId)){
            switch (account.getSystemUser()){
                case 5:
                case 6:
                    enterpriseLibraryMapper.delete(new QueryWrapper<EnterpriseLibrary>().eq("library_id", libraryId));
                    break;
                case 7:
                case 8:
                    eductionLibraryMapper.delete(new QueryWrapper<EducationLibrary>().eq("library_id", libraryId));
                    break;
            }
        }else {
            throw new BusinessException("have.no.permission", ResultEnum.PROMPT.getCode());
        }
    }


    // 查询企业或教育的公共库
    public PageBaseResponse<Library> getPublicLib(String order, long page, long size){
        Long accountId = UserContext.getUserHolder().getId();
        Account account = accountMapper.selectById(accountId);
        if (Objects.isNull(account.getOrganizationId())){
            throw new BusinessException("未查询到您的组织信息，无法获取公共库的元素", ResultEnum.PROMPT.getCode());
        }
        Long organizationId = account.getOrganizationId();
        long offset = (page - 1) * size;
        List<Library> libraries = libraryMapper.selectCommonLib(organizationId, order, size, offset);
        Long count = libraryMapper.selectCommonLibCount(organizationId);
        long pages = (long) Math.ceil(count / size);
        return new PageBaseResponse<>(libraries, page, size, count, pages == 0 ? 1 : pages);
    }

    // 管理员查所有子账号的library
    public PageBaseResponse<Library> getAllSubAccLib(String order, long page, long size){
        // 1、判断当前账号是不是管理员
        Long accountId = UserContext.getUserHolder().getId();
        Account account = accountMapper.selectById(accountId);
        long offset = (page - 1) * size;
        switch(account.getSystemUser()){
            case 5:
            case 7:
                if (Objects.isNull(account.getOrganizationId())){
                    throw new BusinessException("未查询到您的组织信息，无法获取元素", ResultEnum.PROMPT.getCode());
                }
                List<Library> libraries = libraryMapper.selectAllSubAccLib(account.getOrganizationId(), order, size, offset);
                Long count = libraryMapper.selectAllSubAccLibCount(account.getOrganizationId());
                long pages = (long) Math.ceil(count / size);
                return new PageBaseResponse<>(libraries, page, size, count, pages == 0 ? 1 : pages);
            default:
                throw new BusinessException("have.no.permission", ResultEnum.PROMPT.getCode());
        }
    }

    /**
     * 将系统sketch添加到个人library
     */
    public String addSysSketchToLibrary(Long clothId, String path) {
        // 1. 判断当前路径是不是系统sketch
        if (!path.startsWith("aida-sys-image/images")) {
            throw new BusinessException("Non-system Sketch file cannot be added to personal library.", ResultEnum.PROMPT.getCode());
        }

        // 2. 是。获取当前用户id,随机生成4位数
        String sourceObject = path.substring(path.indexOf("/") + 1);
        String subPath = sourceObject.substring(sourceObject.indexOf("images/") + "images/".length(), sourceObject.lastIndexOf("."));
        String gender = subPath.substring(0, subPath.indexOf("/")).equals("female") ? "Female" : "Male";
        String category = subPath.substring(subPath.indexOf("/") + 1, subPath.lastIndexOf("/"));
        CollectionLevel2TypeEnum collectionLevel2TypeEnum = CollectionLevel2TypeEnum.ofWithLoweCase(category);
        if (Objects.nonNull(collectionLevel2TypeEnum)){
            category = collectionLevel2TypeEnum.getRealName();
        } else {
            category = OUTWEAR.getRealName();
        }
        String suffix = sourceObject.substring(sourceObject.lastIndexOf(".") + 1);
        Long userId = UserContext.getUserHolder().getId();
        // 由于允许将同一张系统sketch多次添加到个人library，但是路径相对固定，所以这里添加随机数以作区分
        String name = subPath.substring(subPath.lastIndexOf("/") + 1) + "_" + RandomsUtil.generateVerifyCode(1000L, 9999L);
        String targetObject = userId + "/sketchboard/" + gender.toLowerCase() + "/" + category + "/" +
                name + "." + suffix;

        // 3. 复制图片到用户个人图片文件夹下
        minioUtil.copyObject(sysImage, sourceObject, users, targetObject);

        // 4. 存储到数据库中
        String targetPath = users + "/" + targetObject;
        String md5 = MD5Utils.encryptFile(minioUtil.getPreSignedUrl(targetPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME), false);
        Library library = new Library(userId, CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName(),
                category, gender, "Adult", name, targetPath, md5, new Date());
        saveOne(library);

        // 5. 更新designItemDetail中的图片路径
        if (Objects.nonNull(clothId)) {
            designItemDetailService.updateDetailPathById(clothId, targetPath);
        }
        return minioUtil.getPreSignedUrl(targetPath, CommonConstant.MINIO_IMAGE_EXPIRE_TIME);
    }

    /**
     * todo 低分辨率下载
     */
    public void downloadSysSketchWithWatermark() {
    }

}
