package cn.timer.api.service.impl;

import cn.timer.api.bean.disk.DiskFiles;
import cn.timer.api.config.sftp.SftpConfiguration;
import cn.timer.api.controller.disk.constant.FileAddressConstant;
import cn.timer.api.dto.disk.FileInfoDto;
import cn.timer.api.service.FtpService;
import cn.timer.api.service.OSSService;
import cn.timer.api.utils.Md5;
import cn.timer.api.utils.aliyun.OSSUtil;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class FtpServiceImpl implements FtpService {

    @Autowired
    private SftpConfiguration config;
    @Autowired
    private OSSUtil oss;
    @Autowired
    private OSSService ossService;


    @Override
    public boolean createDirs(String dirPath, ChannelSftp sftp) {
        if (dirPath != null && !dirPath.isEmpty() && sftp != null) {
            String[] dirs = Arrays.stream(dirPath.split("/")).filter(StringUtils::hasLength).toArray(String[]::new);

            for (String dir : dirs) {
                try {
                    sftp.cd(dir);
                    //log.info("stfp切换到目录:{}", dir);
                } catch (Exception e) {
                    try {
                        sftp.mkdir(dir);
                        //log.info("sftp创建目录:{}", dir);
                    } catch (SftpException e1) {
                        log.error("[sftp创建目录失败]:{}", dir, e1);
                        e1.printStackTrace();
                        throw new RuntimeException("sftp创建目录失败");
                    }
                    try {
                        sftp.cd(dir);
                        //log.info("stfp切换到目录:{}", dir);
                    } catch (SftpException e1) {
                        log.error("[sftp切换目录失败]:{}", dir, e1);
                        e1.printStackTrace();
                        throw new RuntimeException("sftp切换目录失败");
                    }
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public List<FileInfoDto> uploadFile(int orgCode, MultipartFile[] files) {

        List<FileInfoDto> resultStrs = new ArrayList<FileInfoDto>();
        //存储地址判断
        if (FileAddressConstant.PHYSICS_OSS.equals(config.getFileAddress())) {
            ChannelSftp sftp = config.getSftpSocket();
            try {
                sftp.cd(config.getRoot());
                //log.info("sftp连接host", config.getRoot());
                boolean dirs = this.createDirs(config.getTargetPath(), sftp);
                if (!dirs) {
                    log.error("sftp创建目录失败", config.getTargetPath());
                    throw new RuntimeException("上传文件失败");
                }
                FileInfoDto dto = null;
                for (MultipartFile file : files) {
                    dto = new FileInfoDto();
                    String fileName = "";
                    String name = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));
                    String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
                    if (config.isReservedName()) {
                        fileName = Md5.md5(name + UUID.randomUUID().toString()) + suffix;
                    } else {
                        fileName = UUID.randomUUID().toString() + suffix;
                    }
                    sftp.put(file.getInputStream(), fileName);
                    dto.setUrlPath(config.getServerUrl() + "/" + fileName);
                    dto.setResourceFileName(name);
                    dto.setFileName(config.getRoot() + config.getTargetPath() + "/" +fileName);

                    /*Float size = Float.parseFloat(String.valueOf(file.getSize())) / 1024;
                    BigDecimal b = new BigDecimal(size);
                    // 2表示2位 ROUND_HALF_UP表明四舍五入,
                    size = b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();*/
                    dto.setFileSize(file.getSize());
                    dto.setFileSuffix(suffix);

                    resultStrs.add(dto);
                }
            } catch (Exception e) {
                log.error("上传文件失败", config.getTargetPath(), e);
                e.printStackTrace();
                throw new RuntimeException("上传文件失败");
            } finally {
                config.returnSftpSocket(sftp);
            }
        } else if (FileAddressConstant.ALIYUN_OSS.equals(config.getFileAddress())) {
            resultStrs = ossService.uploadFile(orgCode, "disk",files);
        }
        return resultStrs;
    }


    /**
     * 下载单个文件
     *
     * @param diskFiles:远程下载目录
     * @return
     */
    @Override
    public InputStream downloadFile(DiskFiles diskFiles) {
        //存储地址判断
        InputStream nputStream = null;
        if (diskFiles.getUrlPath().indexOf(config.getServerUrl())!=-1) {
            ChannelSftp sftp = config.getSftpSocket();
            try {
                // sftp.cd(remotePath);
                // mkdirs(localPath + localFileName);
                //sftp.get(remotePath, fieloutput);
                nputStream = sftp.get(diskFiles.getDiskPath());
                if (log.isInfoEnabled()) {
                    log.info("===DownloadFile:" + diskFiles.getDiskPath() + " success from sftp.");
                }
                return nputStream;
            } catch (SftpException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                config.returnSftpSocket(sftp);
            }
        }else if (FileAddressConstant.ALIYUN_OSS.equals(config.getFileAddress())) {
            nputStream = oss.downloadFileInputStream(diskFiles.getDiskPath());
        }
        return nputStream;
    }

    @Override
    public boolean deleteFile(List<String> targetPath) {
        ChannelSftp sftp = null;
        try {
            sftp = config.getSftpSocket();
            sftp.cd(config.getRoot());
            for (String path : targetPath) {
                sftp.rm(path);
            }
            return true;
        } catch (Exception e) {
            log.error("删除文件失败", targetPath, e);
            e.printStackTrace();
            throw new RuntimeException("删除文件失败");
        } finally {
            config.returnSftpSocket(sftp);
        }
    }
}