package com.sunxung.factoring.service.sys.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.util.CodeUtil;
import com.sunxung.factoring.component.util.CollectionUtil;
import com.sunxung.factoring.component.util.FileUtil;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.sys.FileStorageDO;
import com.sunxung.factoring.entity.sys.SysAttachmentRef;
import com.sunxung.factoring.mapper.sys.FileStorageDAO;
import com.sunxung.factoring.mapper.sys.SysAttachmentRefMapper;
import com.sunxung.factoring.service.sys.FileService;
import com.sunxung.factoring.service.sys.FileStorageService;
import com.sunxung.factoring.service.sys.ISysAttachmentRefService;
import com.sunxung.factoring.service.sys.dto.AttachmentDto;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 通用附件关系表 服务实现类
 * </p>
 *
 * @author daxian
 * @since 2022-02-28
 */
@Service
public class SysAttachmentRefServiceImpl extends ServiceImpl<SysAttachmentRefMapper, SysAttachmentRef> implements ISysAttachmentRefService {

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private FileService fileService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveFileAndRef(List<MultipartFile> multipartFile, AttachmentDto attachmentDto) {
        try {
            if (null != multipartFile && multipartFile.size() > 0) {
                for (MultipartFile multiFile : multipartFile) {
                    FileStorage fileStorage = fileStorageService.addFileStorage(multiFile,
                            attachmentDto.getChildEnum());
                    if (null != fileStorage) {
                        SysAttachmentRef sysAttachmentRef = SysAttachmentRef.builder()
                                .setModuleName("")
                                .setEntityName(attachmentDto.getChildEnum().getCode())
                                .setEntityId(attachmentDto.getEntityId())
                                .setFileStorageId(fileStorage.getId())
                                .setFileStorageType(SysAttachmentRef.STORAGE_TYPE_LOCAL)
                                .setEntityTypeExpand(attachmentDto.getTypeExpand())
                                .build();
                        save(sysAttachmentRef);
                    }
                }
            }
        } catch (Exception e) {
            log.error(attachmentDto.getChildEnum().getCname() + "上传出错：" + e.getMessage());
            throw new BusinessException(CodeUtil.FAIL, e.getMessage());
        }

        return true;
    }

    @Override
    public boolean saveFileAndRefHis(List<FileStorage> fileStorageList, AttachmentDto attachmentDto) {

        if (fileStorageList != null && fileStorageList.size() > 0) {
            fileStorageList.stream().forEach(fileStorage -> {
                FileStorage storage = fileStorageService.add(fileStorage);
                if (null != storage) {
                    SysAttachmentRef sysAttachmentRef = SysAttachmentRef.builder()
                            .setModuleName("")
                            .setEntityName(attachmentDto.getChildEnum().getCode())
                            .setEntityId(attachmentDto.getEntityId())
                            .setFileStorageId(fileStorage.getId())
                            .setFileStorageType(SysAttachmentRef.STORAGE_TYPE_LOCAL)
                            .setEntityTypeExpand(attachmentDto.getTypeExpand())
                            .build();
                    save(sysAttachmentRef);
                }
            });
        }


        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveRef(List<Long> fileIdList, AttachmentDto attachmentDto) {
        if (fileIdList != null && fileIdList.size() > 0) {
            List attachments = new ArrayList();
            for (Long fileId : fileIdList) {
                SysAttachmentRef sysAttachmentRef = SysAttachmentRef.builder()
                        .setEntityId(attachmentDto.getEntityId())
                        .setFileStorageId(fileId)
                        .setEntityName(attachmentDto.getChildEnum().getCode())
                        .setEntityTypeExpand(attachmentDto.getTypeExpand())
                        .build();
                attachments.add(sysAttachmentRef);
            }
            return saveBatch(attachments);
        }

        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeFilestorageAndRef(AttachmentDto attachmentDto) {
        List<SysAttachmentRef> list = lambdaQuery()
                .eq(SysAttachmentRef::getEntityId, attachmentDto.getEntityId())
                .eq(SysAttachmentRef::getEntityName, attachmentDto.getChildEnum().getCode())
                .eq(StringUtils.isNoneBlank(attachmentDto.getTypeExpand()), SysAttachmentRef::getEntityTypeExpand, attachmentDto.getTypeExpand())
                .list();

        if (list != null && list.size() > 0) {
            list.forEach(ref -> {
                fileStorageService.delete(ref.getFileStorageId());
                removeById(ref.getId());
            });
        }
        return true;
    }

    @Override
    public boolean removeFileAndRef(AttachmentDto attachmentDto) {
        List<SysAttachmentRef> list = lambdaQuery()
                .eq(SysAttachmentRef::getEntityId, attachmentDto.getEntityId())
                .eq(SysAttachmentRef::getEntityName, attachmentDto.getChildEnum().getCode())
                .eq(StringUtils.isNoneBlank(attachmentDto.getTypeExpand()), SysAttachmentRef::getEntityTypeExpand, attachmentDto.getTypeExpand())
                .list();

        if (list != null && list.size() > 0) {
            list.forEach(ref -> {
                fileStorageService.deleteFile(ref.getFileStorageId());
                fileStorageService.deleteFileStorage(ref.getFileStorageId());
                removeById(ref.getId());
            });
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeFilestorageAndRef(List<Long> deleteFileIds) {
        if (deleteFileIds != null && deleteFileIds.size() > 0) {
            deleteFileIds.stream().forEach(fileId -> {
                remove(new QueryWrapper<SysAttachmentRef>().eq("file_storage_id", fileId));
                fileStorageService.delete(fileId);
            });
        }
        return true;
    }

    @Override
    public boolean removeRef(AttachmentDto attachmentDto) {
        List<SysAttachmentRef> list = lambdaQuery()
                .eq(SysAttachmentRef::getEntityId, attachmentDto.getEntityId())
                .eq(SysAttachmentRef::getEntityName, attachmentDto.getChildEnum().getCode())
                .eq(StringUtils.isNoneBlank(attachmentDto.getTypeExpand()), SysAttachmentRef::getEntityTypeExpand, attachmentDto.getTypeExpand())
                .list();
        if (list != null && list.size() > 0) {
            list.forEach(ref -> removeById(ref.getId()));
        }
        return false;
    }

    @Override
    public List<FileStorage> getFiles(AttachmentDto attachmentDto) {
        List<SysAttachmentRef> list = lambdaQuery()
                .eq(SysAttachmentRef::getEntityId, attachmentDto.getEntityId())
                .eq(SysAttachmentRef::getEntityName, attachmentDto.getChildEnum().getCode())
                .eq(StringUtils.isNoneBlank(attachmentDto.getTypeExpand()), SysAttachmentRef::getEntityTypeExpand, attachmentDto.getTypeExpand())
                .list();

        List<FileStorage> fileStorageList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (SysAttachmentRef sysAttachmentRef : list) {
                FileStorage fileStorage = fileStorageService.get(sysAttachmentRef.getFileStorageId());
                if (fileStorage != null) {
                    fileStorageList.add(fileStorage);
                }
            }
        }

        return fileStorageList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileStorage copyFile(FileStorage fileStorage, FileModuleDict.ChildEnum moduleType, AttachmentDto attachmentDto) {

        if (fileStorage != null) {
            File sourceFile = new File(fileStorage.getAbsolutePath());
            if (sourceFile.exists()) {
                String fileName = FileUtil.randomFileName();
                String absolutePath = FileUtil.getAbsolutePath(fileName, fileStorage.getFileType(), moduleType);
                File targetFile = new File(absolutePath);
                try {
                    FileUtils.copyFile(sourceFile, targetFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                //新建FileStorage
                FileStorage newFileStorage = new FileStorage(fileName, fileStorage.getOriginalName(), absolutePath, moduleType);
                fileStorageService.add(newFileStorage);

                if (newFileStorage.getId() != null) {
                    SysAttachmentRef sysAttachmentRef = SysAttachmentRef.builder()
                            .setEntityId(attachmentDto.getEntityId())
                            .setFileStorageId(newFileStorage.getId())
                            .setEntityName(moduleType.getCode())
                            .setEntityTypeExpand(attachmentDto.getTypeExpand())
                            .build();
                    save(sysAttachmentRef);
                }
                return newFileStorage;
            }
        }
        return null;
    }

    @Override
    public List<FileStorage> getCfiles(AttachmentDto attachmentDto) {

        List<FileStorageDO> fileStorageDOList = fileService.findByBusinessId(attachmentDto.getEntityId(), attachmentDto.getChildEnum().getCode());
        List<FileStorage> fileStorageList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(fileStorageDOList)){
            for (FileStorageDO fileStorageDO:fileStorageDOList ) {
                //String fileName, String originalName, String absolutePath, FileModuleDict.ChildEnum moduleType
                File file = new File(fileStorageDO.getAbsolutePath());
                FileStorage fileStorage = new FileStorage();
                fileStorage.setAbsolutePath(file.getAbsolutePath());
                fileStorage.setPath(file.getPath());
                fileStorage.setOriginalName(fileStorageDO.getOriginalName());
                fileStorage.setSize(file.length());
                fileStorage.setFileType(FileUtil.getSuffix(fileStorageDO.getOriginalName()));
//                FileStorage fileStorage = new FileStorage(file.getName(),fileStorageDO.getOriginalName(),fileStorageDO.getAbsolutePath(),attachmentDto.getChildEnum());
                fileStorageList.add(fileStorage);
            }
        }

        return fileStorageList;
    }
}
