package com.hzya.frame.sys.file.upload.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.hzya.frame.basedao.service.impl.BaseService;
import com.hzya.frame.dateutil.DateUtil;
import com.hzya.frame.fileutil.FileUtils;
import com.hzya.frame.sys.businessFile.dao.IBusinessFileDao;
import com.hzya.frame.sys.businessFile.entity.BusinessFileEntity;
import com.hzya.frame.sys.file.upload.dao.IFileUploadDao;
import com.hzya.frame.sys.file.upload.entity.FileResultEntity;
import com.hzya.frame.sys.file.upload.entity.FileUploadDto;
import com.hzya.frame.sys.file.upload.entity.FileUploadEntity;
import com.hzya.frame.sys.file.upload.service.IFileUploadService;
import com.hzya.frame.uuid.UUIDLong;
import com.hzya.frame.web.action.SessionContext;
import com.hzya.frame.web.exception.BaseSystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @description: 系统文件上传  service
 * @tableName: sys_file
 * @entityName: FileUploadEntity
 * @author: gjh
 * @history: 1.0
 */
@Service(value = "sys_fileUploadService")
public class FileUploadServiceImpl extends BaseService<FileUploadEntity, Long> implements IFileUploadService {
    @Value("${savefile.path}")
    public String DSK;

    @Value("${savefile.pluginpath}")
    public String PLUGINPATH;

    protected IFileUploadDao fileUploadDao;

    @Autowired
    private IBusinessFileDao businessFileDao;

    @Autowired
    public void setFileUploadDao(IFileUploadDao dao) {

        this.fileUploadDao = dao;
        this.dao = dao;
    }

    @Override
    public FileUploadEntity fileUpload(MultipartFile file, FileUploadDto entity) throws Exception {
        /** 获取系统设置文件存放的盘符*/
        StringBuffer stringBuffer = new StringBuffer();
        /** 获取根目录*/
        //stringBuffer.append(DSK);
        /** 根据当前日期创建文件目录*/
        String nowDateString = DateUtil.dateToString(new Date(), "yyyy-MM-dd");

        /** 判断传入的文件是否是属于业务的文件数据,如果是则根据业务单据去生成文件夹，否则，按照日期生成*/
        if (entity.isFileFlag() && entity.getBusinessType() != null && !"".equals(entity.getBusinessType())) {
            /** 没有单票ID临时把文件放在default目录下面*/
            /** 创建默认文件夹*/
            stringBuffer.append(File.separator+entity.getBusinessType());
            /** 根据当前日期生成文件夹*/
            stringBuffer.append(File.separator + nowDateString);
        } else {
            /** 创建默认文件夹*/
            stringBuffer.append(File.separator+"default");
            /** 拼接上当前日期*/
            stringBuffer.append(File.separator + nowDateString);
        }
        /** 获取到拼接完成的文件属性*/
        String path = stringBuffer.toString();
        /** 保存到file表信息*/
        FileUploadEntity fileUploadEntity = saveFile(file, path, "附件备注",entity.getFileType());
        /**当fileType为2时，存储的是插件附件*/
        if(entity.getFileType().equals("2")){
            path = PLUGINPATH + fileUploadEntity.getFilepath();
        }else{
            path = DSK + fileUploadEntity.getFilepath();
        }

        /** 创建文件夹*/
        FileUtils.createDir(path);
        File uploadFile = new File(path);
        file.transferTo(uploadFile);
        return fileUploadEntity;
    }

    @Override
    public FileUploadEntity pluginfileUpload(MultipartFile file, FileUploadDto entity,String pluginPackageName) throws Exception {

        // 创建一个临时文件
        File fileT = new File(file.getOriginalFilename());
        // 将 MultipartFile 的内容写入文件
        try (FileOutputStream fos = new FileOutputStream(fileT)) {
            // 获取文件内容的字节数组
            byte[] bytes = file.getBytes();
            fos.write(bytes);
        }

        ZipFile zipFile = new ZipFile(fileT);//创建压缩文件对象
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        boolean xmlflag = false;
        boolean classflag = false;
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            if(xmlflag == false){
                if(entry.getName().contains("cfgHome/plugin/"+pluginPackageName) && entry.isDirectory()){
                    xmlflag = true;
                }
            }
            if(classflag == false){
                if(entry.getName().contains("com/hzya/frame/plugin/"+pluginPackageName) && entry.isDirectory()){
                    classflag = true;
                }
            }
            if(xmlflag && classflag){
                break;
            }
        }
        if(xmlflag == false || classflag == false){
            throw new BaseSystemException("插件附件不符合规范或插件包名填写错误，请检查！");
        }
        fileT.delete();
        zipFile.close();


        /** 获取系统设置文件存放的盘符*/
        StringBuffer stringBuffer = new StringBuffer();
        /** 获取根目录*/
        //stringBuffer.append(DSK);
        /** 根据当前日期创建文件目录*/
        String nowDateString = DateUtil.dateToString(new Date(), "yyyy-MM-dd");

        /** 判断传入的文件是否是属于业务的文件数据,如果是则根据业务单据去生成文件夹，否则，按照日期生成*/
        if (entity.isFileFlag() && entity.getBusinessType() != null && !"".equals(entity.getBusinessType())) {
            /** 没有单票ID临时把文件放在default目录下面*/
            /** 创建默认文件夹*/
            stringBuffer.append(File.separator+entity.getBusinessType());
            /** 根据当前日期生成文件夹*/
            stringBuffer.append(File.separator + nowDateString);
        } else {
            /** 创建默认文件夹*/
            stringBuffer.append(File.separator+"default");
            /** 拼接上当前日期*/
            stringBuffer.append(File.separator + nowDateString);
        }
        /** 获取到拼接完成的文件属性*/
        String path = stringBuffer.toString();
        /** 保存到file表信息*/
        FileUploadEntity fileUploadEntity = saveFile(file, path, "附件备注",entity.getFileType());
        /**当fileType为2时，存储的是插件附件*/
        if(entity.getFileType().equals("2")){
            path = PLUGINPATH + fileUploadEntity.getFilepath();
        }else{
            path = DSK + fileUploadEntity.getFilepath();
        }

        /** 创建文件夹*/
        FileUtils.createDir(path);
        File uploadFile = new File(path);
        file.transferTo(uploadFile);
        return fileUploadEntity;
    }
    @Override
    public FileResultEntity fileUpload(MultipartFile file, FileResultEntity entity) throws Exception {
        /** 获取当前登陆人*/
        JSONObject userEntity = SessionContext.getCurrentUser();
        /** 获取系统设置文件存放的盘符*/
        StringBuffer stringBuffer = new StringBuffer();
        /** 获取根目录*/
            stringBuffer.append(DSK);


        /** 获取当前人所在的公司，用ID和公司名称拼接*/
//        stringBuffer.append("/" + userEntity.getOrg_name() + "_" + userEntity.getOrg_id());
        /** 根据当前日期创建文件目录*/
        String nowDateString = DateUtil.dateToString(new Date(), "yyyy-MM-dd");

        /** 判断传入的文件是否是属于业务的文件数据,如果是则根据业务单据去生成文件夹，否则，按照日期生成*/
        if (entity.isFileFlag()) {
            /** 获取单票ID，判断单票ID是否存在*/
            Long ticket_id = entity.getTicket_id();
            if (ticket_id != null) {
                /** 拼接上单票类型*/
                stringBuffer.append("/ticket_" + ticket_id);
                /** 拼接上业务类型和业务ID*/
                stringBuffer.append("/" + entity.getBusiness_type() + "_" + entity.getBusiness_id());
            } else {
                /** 没有单票ID临时把文件放在default目录下面*/
                /** 创建默认文件夹*/
                stringBuffer.append("/default");
                /** 根据当前日期生成文件夹*/
                stringBuffer.append("/" + nowDateString);
            }

        } else {
            /** 创建默认文件夹*/
            stringBuffer.append("/default");
            /** 拼接上当前日期*/
            stringBuffer.append("/" + nowDateString);
        }
        /** 获取到拼接完成的文件属性*/
        String path = stringBuffer.toString();
        /** 保存到file表信息*/
        FileUploadEntity fileUploadEntity = saveFile(file, path, "附件备注", userEntity);

        /** 创建文件夹*/
        FileUtils.createDir(path);

        path = path + File.separator + fileUploadEntity.getFilesavename();
        File uploadFile = new File(path);
        file.transferTo(uploadFile);

        /** 设置保存文件表对象*/
        entity.setAttribute(fileUploadEntity);
        entity.setSrc(path);
        return entity;
    }
    @Override
    public FileResultEntity copyFileToBusiness(FileResultEntity entity) throws Exception {

        /** 获取当前登陆人*/
        JSONObject userEntity = SessionContext.getCurrentUser();
        /** 获取系统设置文件存放的盘符*/
        StringBuffer stringBuffer = new StringBuffer();
        /** 获取根目录*/
        stringBuffer.append(DSK);
        /** 获取当前人所在的公司，用ID和公司名称拼接*/
//        stringBuffer.append("/" + userEntity.getOrg_name() + "_" + userEntity.getOrg_id());
        /** 获取单票ID，判断单票ID是否存在*/
        Long ticket_id = entity.getTicket_id();

        if (ticket_id != null) {
            /** 拼接上单票类型*/
            stringBuffer.append("/ticket_" + ticket_id);

            /** 根据单票的ID获取到单票下的所有的file文件*/
            BusinessFileEntity queryEntity = new BusinessFileEntity();
            queryEntity.setTicket_id(ticket_id);

            List<BusinessFileEntity> businessFileEntityList = businessFileDao.query(queryEntity);

            if (null != businessFileEntityList && businessFileEntityList.size() > 0) {
                /** 把查询到的File放到单票下面*/
                for (BusinessFileEntity businessFileEntity : businessFileEntityList) {
                    String fileSaveName = businessFileEntity.getFile_save_name();
                    /** 原来的文件路径*/
                    String oldPath = businessFileEntity.getFile_path() + "/" + fileSaveName;
                    /** 拼接上业务类型和业务ID*/
                    stringBuffer.append("/" + businessFileEntity.getBusiness_type() + "_" + businessFileEntity.getBusiness_id());
                    String newPath = stringBuffer.toString();
                    //创建文件夹
                    FileUtils.createDir(newPath);
                    //根据老文件获取文件，写到新的文件夹下面
                    File oldFile = new File(oldPath);
                    //获取流
                    InputStream in = new FileInputStream(oldFile);
                    //创建文件
                    MockMultipartFile mockMultipartFile = new MockMultipartFile(fileSaveName, in);
                    File uploadFile = new File(newPath);
                    /** 文件写入到新的路径里面*/
                    mockMultipartFile.transferTo(uploadFile);
                    //修改附件的新路径
                    FileUploadEntity fileUploadEntity = new FileUploadEntity();
                    fileUploadEntity.setFilesavename(fileSaveName);
                    fileUploadEntity.setFilepath(newPath);

                    fileUploadDao.updatePathBySaveName(fileUploadEntity);

                    //删除老文件
                    FileUtils.deleteFileByFile(oldFile);

                }
            }

        }
        return entity;
    }

    /****
     * 根据fileSaveName删除附件
     * @param   businessFileId 业务文件的ID
     * @param businessType  删除类型   1，业务删除（业务删除时候，需要把文件备份一份到指定的文件夹），2，非业务删除（直接删除文件）
     * @param fileSaveName  附件的唯一名称
     * @Author guojh
     * @Date 2019/3/27 15:56
     * @Param [businessType, fileSaveName]
     * @return boolean
     **/
    @Override
    public boolean deleteFileByFileSaveName(Long businessFileId, String businessType, String fileSaveName) throws Exception {
        /** 是否删除成功  true 成功，false 失败*/
        boolean flag = false;
        /** 获取当前登陆人*/
        JSONObject userEntity = SessionContext.getCurrentUser();
        /** 获取系统设置文件存放的盘符*/
        StringBuffer stringBuffer = new StringBuffer();
        /** 获取根目录*/
        stringBuffer.append(DSK);
        /** 获取当前人所在的公司，用ID和公司名称拼接*/
//        stringBuffer.append("/" + userEntity.getOrg_name() + "_" + userEntity.getOrg_id());
        /** 根据当前日期创建文件目录*/
        String nowDateString = DateUtil.dateToString(new Date(), "yyyy-MM-dd");
        stringBuffer.append("/bak/" + nowDateString);
        if (null == fileSaveName || "".equals(fileSaveName)) {
            throw new BaseSystemException("附件唯一名称为空！请检查参数");
        }
        FileUploadEntity fileUploadEntity = new FileUploadEntity();
        fileUploadEntity.setFilesavename(fileSaveName);
        /** 根据唯一名称查询附件信息*/
        fileUploadEntity = fileUploadDao.queryOne(fileUploadEntity);
        if (null == fileUploadEntity) {
            throw new BaseSystemException("附件未查询到！请检查file_save_name:" + fileSaveName + "是否正确!");
        }
        /** 业务删除*/
        if ("1".equals(businessType)) {
            if (null == businessFileId) {
                throw new BaseSystemException("业务附件表ID为空，请查看是否业务类型错误!");
            }
            /** 原来的文件路径*/
            String oldPath = fileUploadEntity.getFilepath() + "/" + fileSaveName;
            /** 拼接上业务类型和业务ID*/
            String newPath = stringBuffer.toString();
            //根据老文件获取文件，写到新的文件夹下面
            File oldFile = new File(oldPath);
            //获取流
            InputStream in = new FileInputStream(oldFile);
            //创建文件
            MockMultipartFile mockMultipartFile = new MockMultipartFile(fileUploadEntity.getFilename(), in);
            //创建文件夹
            FileUtils.createDir(newPath);
            File uploadFile = new File(newPath + "/" + fileUploadEntity.getFilename());
            /** 文件写入到新的路径里面*/
            mockMultipartFile.transferTo(uploadFile);
            /** 逻辑删除文件表*/
            fileUploadDao.logicRemove(fileUploadEntity);
            /** 逻辑删除业务表*/
            BusinessFileEntity businessFileEntity = new BusinessFileEntity();
            businessFileEntity.setId(String.valueOf(businessFileId));
            businessFileDao.logicRemove(businessFileEntity);
            flag = true;
        }
        /** 非业务删除*/
        if ("2".equals(businessType)) {
            String filePath = fileUploadEntity.getFilepath() + "/" + fileUploadEntity.getFilesavename();
            FileUtils.deleteFile(filePath);
            flag = true;
        }

        return flag;
    }

    /***
     * 保存附件到附件表方法
     * @param file
     * @param filepath
     * @param description
     * @return
     */
    private FileUploadEntity saveFile(MultipartFile file, String filepath, String description,String fileType) {
        /*** UUID生成File的新名称*/
        Long id = UUIDLong.longUUID();
        Long fileNewName = UUIDLong.longUUID();
        /** 获取文件的扩展名*/
        String fileName = file.getOriginalFilename();
        /** 截取扩展名*/
        String type = file.getContentType();
        FileUploadEntity fileUploadEntity = new FileUploadEntity();
        fileUploadEntity.setId(String.valueOf(id));
        fileUploadEntity.setFilename(fileName);
        fileUploadEntity.setFilesavename(String.valueOf(fileNewName));
        fileUploadEntity.setType(type);
        fileUploadEntity.setFileType(fileType);
        fileUploadEntity.setFile_size(file.getSize());
        fileUploadEntity.setDescription(description);
        fileUploadEntity.setFilepath(filepath+ File.separator +fileUploadEntity.getFilesavename());
        fileUploadEntity.setCreate_user_id(StpUtil.getLoginIdAsString());
        fileUploadEntity.setModify_user_id(StpUtil.getLoginIdAsString());
        fileUploadEntity.setCreate_time(new Date());
        fileUploadEntity.setModify_time(new Date());
        fileUploadEntity.setSts("Y");
        fileUploadDao.save(fileUploadEntity);
        return fileUploadEntity;
    }
    /***
     * 保存附件到附件表方法
     * @param file
     * @param filepath
     * @param description
     * @return
     */
    private FileUploadEntity saveFile(MultipartFile file, String filepath, String description, JSONObject userEntity) {
        /*** UUID生成File的新名称*/
        Long id = UUIDLong.longUUID();
        Long fileNewName = UUIDLong.longUUID();
        /** 获取文件的扩展名*/
        String fileName = file.getOriginalFilename();
        /** 截取扩展名*/
        String type = file.getContentType();

        FileUploadEntity fileUploadEntity = new FileUploadEntity();
        fileUploadEntity.setId(String.valueOf(id));
        fileUploadEntity.setFilename(fileName);
        fileUploadEntity.setFilesavename(String.valueOf(fileNewName));
        fileUploadEntity.setType(type);
        fileUploadEntity.setFile_size(file.getSize());
        fileUploadEntity.setDescription(description);
        fileUploadEntity.setFilepath(filepath);
        fileUploadEntity.setCreate_user_id(userEntity == null?null:userEntity.getString("id"));
        fileUploadEntity.setModify_user_id(userEntity == null?null:userEntity.getString("id"));
        fileUploadDao.save(fileUploadEntity);

        return fileUploadEntity;
    }
}
