package com.fdkankan.fyun.local;

import cn.hutool.core.io.FileUtil;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.fyun.constant.FYunConstants;
import com.fdkankan.fyun.constant.FYunTypeEnum;
import com.fdkankan.fyun.face.AbstractFYunFileService;
import com.fdkankan.fyun.local.constant.LocalConstants;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

@Component
@ConditionalOnProperty(name = "fyun.type", havingValue = "local")
public class LocalFileService extends AbstractFYunFileService {

    private Logger log = LoggerFactory.getLogger(this.getClass().getName());

    @Override
    public String uploadFile(String bucket, byte[] data, String remoteFilePath) {
        try {
            FileUtil.writeBytes(data, getOssPath(bucket, remoteFilePath));
        }catch (Exception e){
            log.error("oss上传文件失败,remoteFilePath:" + remoteFilePath, e);
        }
        return null;
    }

    @Override
    public String uploadFile(String bucket, String filePath, String remoteFilePath) {
        return uploadFile(bucket, filePath, remoteFilePath, null);
    }

    @Override
    public String uploadFile(String bucket, InputStream inputStream, String remoteFilePath) {
        try {
            FileUtil.writeFromStream(inputStream,getOssPath(bucket, remoteFilePath));
        }catch (Exception e){
            log.error("上传文件失败,remoteFilePath:{}", remoteFilePath);
            log.error("上传文件失败", e);
        }
        return null;
    }

    @Override
    public String uploadFile(String bucket, String filePath, String remoteFilePath, Map<String, String> headers) {
        try {
            if (!new File(filePath).exists()) {
                log.warn("文件不存在：{}", filePath);
                return null;
            }
            FileUtil.copy(filePath, getOssPath(bucket, remoteFilePath), true);
        }catch (Exception e){
            log.error("上传文件失败，filePath:{},remoteFilePath:{}", filePath, remoteFilePath);
            log.error("上传文件失败", e);
        }

        return null;
    }

    @Override
    public String uploadFileByCommand(String bucket, String filePath, String remoteFilePath) {
        try {
            String optType = new File(filePath).isDirectory() ? "folder" : "file";
            String command = String.format(fYunConstants.UPLOAD_SH, bucket, filePath, remoteFilePath, FYunTypeEnum.LOCAL.code(), optType);
            log.info("开始上传文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
            callshell(command);
        } catch (Exception e) {
            log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
        }
        return null;
    }

    @Override
    public void downloadFileByCommand(String bucket, String filePath, String remoteFilePath) {
        try {
            String optType = remoteFilePath.contains(".") ? "file" : "folder";
            String command = String.format(fYunConstants.DOWNLOAD_SH, bucket, remoteFilePath, filePath, FYunTypeEnum.LOCAL.code(), optType);
            log.info("开始下载文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
            callshell(command);
        } catch (Exception e) {
            log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
        }
    }

    @Override
    public void deleteFile(String bucket, String remoteFilePath) throws IOException {
        FileUtil.del(getOssPath(bucket, remoteFilePath));
    }

    @Override
    public void deleteFolder(String bucket, String remoteFolderPath) {
        FileUtil.del(getOssPath(bucket, remoteFolderPath));
    }

    @Override
    public void uploadMulFiles(String bucket, Map<String, String> filepaths) {
        for (Map.Entry<String, String> entry : filepaths.entrySet()) {
            uploadFile(bucket, entry.getKey(), entry.getValue(), null);
        }
    }


    @Override
    public List<String> listRemoteFiles(String bucket, String sourcePath) {
        return listRemoteFiles(bucket, sourcePath, true);
    }

    private List<String> listRemoteFiles(String bucket, String sourcePath, Boolean shutdown) {
        return FileUtil.loopFiles(getOssPath(bucket, sourcePath)).stream()
                .map(f -> f.getAbsolutePath().replace(LocalConstants.BASE_PATH.concat(bucket).concat(File.separator), ""))
                .collect(Collectors.toList());
    }

    @Override
    public void copyFileBetweenBucket(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
        try {
            FileUtil.copyContent(new File(getOssPath(sourceBucketName, sourcePath)), new File(getOssPath(targetBucketName, targetPath)), true);
        }catch (Exception e){
            log.error("复制文件失败，sourcePath:{},targetPath:{}",sourcePath,targetPath);
            log.error("复制文件失败", e);
        }
    }

    @Override
    public void copyFilesBetweenBucket(String sourceBucketName, String targetBucketName, Map<String, String> pathMap) {
        if (ObjectUtils.isEmpty(pathMap)) {
            return;
        }
        for (Map.Entry<String, String> entry : pathMap.entrySet()) {
            copyFileBetweenBucket(sourceBucketName, entry.getKey(), targetBucketName, entry.getValue());
        }
    }

    @Override
    public String getFileContent(String bucketName, String remoteFilePath) {
        try {
            return FileUtil.readUtf8String(getOssPath(bucketName, remoteFilePath));
        }catch (Exception e){
            log.error("读取文件失败，remoteFilePath:{}", remoteFilePath);
            log.error("读取文件失败", e);
            return null;
        }
    }

    @Override
    public boolean fileExist(String bucket, String objectName) {
        return FileUtil.exist(getOssPath(bucket, objectName));
    }

    @Override
    public void downloadFile(String bucket, String remoteFilePath, String localPath) {
        try {
            FileUtil.copy(getOssPath(bucket, remoteFilePath), localPath, true);
        }catch (Exception e){
            log.error("下载文件失败,remoteFilePath：{}，localPath:{}", remoteFilePath, localPath);
            log.error("下载文件失败", e);
        }
    }

    @Override
    public URL getPresignedUrl(String bucket, String url) {
        return null;
    }

    @Override
    public long getSubFileNums(String bucket, String url) {
        return FileUtils.getSubFileNums(new File(getOssPath(bucket, url)));
    }

    @Override
    public void restoreFolder(String bucket, String folderName, Integer priority) {

    }

    @Override
    public void restoreFile(String bucket, String objectName, Integer priority) {

    }

    private String getOssPath(String bucket, String filePath) {
        return LocalConstants.BASE_PATH.concat(bucket).concat(File.separator).concat(filePath);
    }

    @Override
    public Boolean checkStore(String bucket, String url) {
        return null;
    }

    @Override
    public void restoreFolder(String bucket, String url) {

    }

    @Override
    public Integer getRestoreFolderProcess(String bucket, String url) {
        return null;
    }

    @Override
    public Long getSpace(String bucket, String key) {
        String ossPath = getOssPath(bucket, key);
        if(!FileUtil.exist(ossPath)){
            return 0L;
        }
        if(FileUtil.isFile(ossPath)){
            return FileUtil.size(new File(ossPath));
        }
        return FileUtil.loopFiles(ossPath).stream().mapToLong(File::length).sum();
    }
}
