package cn.timer.api.service.impl;

import cn.timer.api.config.sftp.SftpConfiguration;
import cn.timer.api.dto.disk.FileInfoDto;
import cn.timer.api.service.FtpService;
import cn.timer.api.utils.Md5;
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.scheduling.annotation.Async;
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;


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

    @Async("threadPoolTaskExecutor")
    @Override
    public List<FileInfoDto> uploadFile(String targetPath, MultipartFile[] files, boolean reservedName) {
        ChannelSftp sftp = config.getSftpSocket();
        List<FileInfoDto> resultStrs = new ArrayList<FileInfoDto>();
        try {
            sftp.cd(config.getRoot());
            //log.info("sftp连接host", config.getRoot());
            boolean dirs = this.createDirs(targetPath, sftp);
            if (!dirs) {
                log.error("sftp创建目录失败", targetPath);
                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 (reservedName) {
                    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(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);
            }
            return resultStrs;
        } catch (Exception e) {
            log.error("上传文件失败", targetPath, e);
            e.printStackTrace();
            throw new RuntimeException("上传文件失败");
        } finally {
            config.returnSftpSocket(sftp);
        }
    }



    /**
     * 下载单个文件
     *
     * @param remotePath:远程下载目录
     * @return
     */
    @Override
    public InputStream downloadFile(String remotePath) {
        ChannelSftp sftp = config.getSftpSocket();
        InputStream nputStream = null;
        try {
            // sftp.cd(remotePath);
            // mkdirs(localPath + localFileName);
            //sftp.get(remotePath, fieloutput);
            nputStream = sftp.get(remotePath);
            if (log.isInfoEnabled()) {
                log.info("===DownloadFile:" + remotePath + " success from sftp.");
            }
            return nputStream;
        } catch ( SftpException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            config.returnSftpSocket(sftp);
        }
        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);
        }
    }
}