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.response.PageBaseResponse;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.CopyUtil;
import com.ai.da.common.utils.DateUtil;
import com.ai.da.common.utils.FileUtil;
import com.ai.da.common.utils.MinioUtil;
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 com.google.common.base.Function;
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.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author yanglei
 * @since 2022-09-30
 */
@Slf4j
@Service
public class LibraryServiceImpl extends ServiceImpl<LibraryMapper, Library> implements LibraryService {
    @Resource
    private LibraryMapper libraryMapper;
    @Resource
    private SysFileMapper sysFileMapper;
    @Resource
    private FileProperties fileProperties;
    @Resource
    private LibraryModelPointService libraryModelPointService;
    @Resource
    private WorkspaceService workspaceService;
    @Resource
    private ClassificationService classificationService;
    @Resource
    private GenerateService generateService;
    @Resource
    private MinioUtil minioUtil;

    @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;

    @Resource
    private PythonTAllInfoService pythonTAllInfoService;

    private static List<String> top = Arrays.asList(CollectionLevel2TypeEnum.DRESS.getRealName(),
            CollectionLevel2TypeEnum.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<>();
        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 (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");
        IPage<Library> page = getBaseMapper().selectPage(
                new Page<>(query.getPage(), query.getSize()), queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return PageBaseResponse.success(new Page<>());
        }
        Map<Long, LibraryModelPointVO> map = null;
        //封装打点内容
        Boolean isExist = page.getRecords().stream()
                .anyMatch(library -> library.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName()));
        if (isExist) {
            List<Long> libarayIds = page.getRecords().stream()
                    .filter(library -> library.getLevel1Type().equals(LibraryLevel1TypeEnum.MODELS.getRealName()))
                    .map(Library::getId)
                    .collect(Collectors.toList());
            List<LibraryModelPointVO> libraryModelPointVOS = libraryModelPointService.selectByLibraryIds(libarayIds);
            if (!CollectionUtils.isEmpty(libraryModelPointVOS)) {
                map = libraryModelPointVOS.stream().collect(Collectors.toMap(LibraryModelPointVO::getRelationId, v -> v));
            }
        }
        Map<Long, LibraryModelPointVO> finalMap = map;
        IPage<QueryLibraryPageVO> convert = page.convert((Function<Library, QueryLibraryPageVO>) library -> {
            QueryLibraryPageVO libraryPageVO = CopyUtil.copyObject(library, QueryLibraryPageVO.class);
            libraryPageVO.setDesignType(DesignTypeEnum.LIBRARY.getRealName());
            libraryPageVO.setMinIOPath(library.getUrl());
            libraryPageVO.setUrl(minioUtil.getPresignedUrl(library.getUrl(), 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())));
                }
            }
            return libraryPageVO;
        });
        return PageBaseResponse.success(convert);
    }

    @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) && 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:
                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);
                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");
    }

    @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")
                .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::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 = generateService.selectBatchByLibraryId(deleteDTO.getLibraryIds());

        // 2、有，则更新generateDetail表的is_like字段和library_id字段
        if (!generateDetails.isEmpty()){
            generateService.updateLikeStatusBatch(
                    generateDetails.stream().map(GenerateDetail::getId).collect(Collectors.toList()),
                    (byte)0,
                    0L,
                    deleteDTO.getTimeZone()
            );
        }
//        for (Library library : librarys) {
//            if (library.getUrl().startsWith(sysImage)) {
//                continue;
//            }
//            minioUtil.deleteObject(library.getUrl());
//        }

    }

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

    @Resource
    private LibraryCopyMapper libraryCopyMapper;
    @Resource
    private LibraryModelPointCopyMapper libraryModelPointCopyMapper;
    @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);
                                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::getUserName, authPrincipalVo.getUsername());
        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());
            } else {
                library.setLevel3Type(uploadDTO.getModelSex());
            }
            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);
            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;
    }
}
