package com.fdkankan.fyun.http;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.fyun.face.AbstractFYunFileService;
import com.fdkankan.fyun.http.config.HttpFyunConfig;
import com.fdkankan.fyun.http.entity.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

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

    private RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private HttpFyunConfig httpFyunConfig;

    @Override
    public String uploadFile(String bucket, byte[] data, String remoteFilePath) {
        try {
            // 先将文件保存至本地
            String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
            FileUtils.writeFile(httpFyunConfig.getLocalTempPath(), fileName, data);
            uploadFile(bucket,httpFyunConfig.getLocalTempPath() + fileName,remoteFilePath,null);
            FileUtils.deleteFile(httpFyunConfig.getLocalTempPath() + fileName);
        } catch (Exception e) {
            log.error("oss上传文件失败", e);
            e.printStackTrace();
        }
        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 {
            // 先将文件保存至本地
            String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/") + 1);
            FileUtil.writeFromStream(inputStream, httpFyunConfig.getLocalTempPath() + fileName);
            uploadFile(bucket,httpFyunConfig.getLocalTempPath() + fileName,remoteFilePath,null);
            FileUtils.deleteFile(httpFyunConfig.getLocalTempPath() + fileName);
        } catch (Exception e) {
            log.error("oss上传文件失败", e);
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String uploadFile(String bucket, String filePath, String remoteFilePath, Map<String, String> headers) {
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                log.error("要上传的文件不存在：" + filePath);
                return null;
            }
            Map<String, Object> params = new HashMap<>();
            params.put("appName", fYunFileConfig.getKey());
            params.put("secret", fYunFileConfig.getSecret());
            params.put("fileName", filePath);
            params.put("targetPath", remoteFilePath);
            String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getUploadFile();
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
            log.info("Fyun Http Utils upload，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
            if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
                log.error("Fyun Http Utils upload failed!");
            }
            log.info("文件上传成功，path:{}", filePath);
        } catch (Exception e) {
            log.error("oss上传文件失败", e);
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String uploadFileByCommand(String bucket, String filePath, String remoteFilePath) {
        // 上传文件夹
        Map<String, Object> params = new HashMap<>();
        params.put("appName", fYunFileConfig.getKey());
        params.put("secret", fYunFileConfig.getSecret());
        params.put("dirName", filePath);
        params.put("targetPath", remoteFilePath);
        String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getUploadDir();
        ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
        log.info("Fyun Http Utils upload folder，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
        if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
            log.error("Fyun Http Utils upload folder failed!");
        }
        return null;
    }

    @Override
    public void downloadFileByCommand(String bucket, String localPath, String remoteFilePath) {
        // 下载文件夹
        File localFile = new File(localPath);
        if(localFile.isDirectory()){
            if(!localFile.exists()){
                localFile.mkdirs();
            }
            String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
            log.info("未配置文件名，使用默认文件名：{}",fileName);
            localPath = localPath.concat(File.separator).concat(fileName);
        }else if(!localFile.getParentFile().exists()){
            localFile.getParentFile().mkdirs();
        }
        Map<String, Object> params = new HashMap<>();
        params.put("appName", fYunFileConfig.getKey());
        params.put("secret", fYunFileConfig.getSecret());
        params.put("fileName", remoteFilePath);
        params.put("targetPath", localPath);
        String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getDownloadDir();
        ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
        log.info("Fyun Http Utils download folder，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
        if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
            log.error("Fyun Http Utils download folder failed!");
        }
    }

    @Override
    public void downloadByCommand(String bucket, String filePath, String remoteFilePath, boolean isDir) {

    }

    @Override
    public void deleteFile(String bucket, String remoteFilePath) throws IOException {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("appName", fYunFileConfig.getKey());
            params.put("secret", fYunFileConfig.getSecret());
            params.put("fileName", remoteFilePath);
            String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getDeleteFile();
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
            log.info("Fyun Http Utils delete file，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
            if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
                log.error("Fyun Http Utils delete file failed!");
            }
            log.info("文件删除成功，path:{}", remoteFilePath);
        } catch (Exception e) {
            log.error("OSS删除文件失败,key=" + remoteFilePath);
            e.printStackTrace();
        }
    }

    @Override
    public void deleteFolder(String bucket, String remoteFolderPath) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("appName", fYunFileConfig.getKey());
            params.put("secret", fYunFileConfig.getSecret());
            params.put("dirName", remoteFolderPath);
            String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getDeleteDir();
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
            log.info("Fyun Http Utils delete folder，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
            if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
                log.error("Fyun Http Utils delete folder failed!");
            }
            log.info("文件夹删除成功，path:{}", remoteFolderPath);
        } catch (Exception e) {
            log.error("OSS删除文件失败,key=" + remoteFolderPath);
            e.printStackTrace();
        }
    }

    @Override
    public void uploadMulFiles(String bucket, Map<String, String> filepaths) {
        try {
            for (Map.Entry<String, String> entry : filepaths.entrySet()) {
                uploadFile(bucket, entry.getKey(), entry.getValue(), null);
            }
        } catch (Exception e) {
            log.error("OSS批量上传文件失败！");
        }
    }

    @Override
    public List<String> listRemoteFiles(String bucket, String sourcePath) {
        throw new UnsupportedOperationException("不支持列举文件列表!");
    }

    @Override
    public void copyFileBetweenBucket(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("appName", fYunFileConfig.getKey());
            params.put("secret", fYunFileConfig.getSecret());
            params.put("targetDir", targetPath);
            String url;
            if(new File(sourcePath).isDirectory()){
                params.put("dirName", sourcePath);
                url = fYunFileConfig.getEndPoint() + httpFyunConfig.getCopyDir();
            }else{
                params.put("fileName", sourcePath);
                url = fYunFileConfig.getEndPoint() + httpFyunConfig.getCopyFile();
            }
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
            log.info("Fyun Http Utils copy file or dir，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
            if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
                log.error("Fyun Http Utils copy file or dir failed!");
            }
            log.info("文件拷贝成功，path:{}", targetPath);
        } catch (Exception e) {
            log.error("列举文件目录失败,key=" + sourcePath);
        }
    }

    @Override
    public void copyFileBetweenBucketParallel(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {

    }

    @Override
    public void copyFilesBetweenBucket(String sourceBucketName, String targetBucketName, Map<String, String> pathMap) {
        if (ObjectUtils.isEmpty(pathMap)) {
            return;
        }
        try {
            for (Map.Entry<String, String> entry : pathMap.entrySet()) {
                copyFileBetweenBucket(sourceBucketName, entry.getKey(), targetBucketName, entry.getValue());
            }
        } catch (Exception e) {
            log.error("批量复制文件失败!");
        }
    }

    @Override
    public String getFileContent(String bucketName, String remoteFilePath) {
        try {
            // 先将文件下载到本地
            String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
            downloadFile(remoteFilePath, httpFyunConfig.getLocalTempPath() + fileName);
            String content =FileUtils.readFile(httpFyunConfig.getLocalTempPath() + fileName);
            FileUtils.deleteFile(httpFyunConfig.getLocalTempPath() + fileName);
            return content;
        } catch (Exception e) {
            log.error("获取文件内容失败：{}", remoteFilePath);
            return null;
        }
    }

    @Override
    public boolean fileExist(String bucket, String objectName) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("appName", fYunFileConfig.getKey());
            params.put("secret", fYunFileConfig.getSecret());
            params.put("fileName", objectName);
            String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getFileExist();
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
            log.info("Fyun Http Utils file exist，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
            if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
                log.error("Fyun Http Utils copy file failed!");
            }
            return Boolean.parseBoolean(responseEntity.getBody().getData().toString());
        } catch (Exception e) {
            log.error("判断文件是否存在失败：{}", objectName);
            return false;
        }
    }

    @Override
    public void downloadFile(String bucket, String remoteFilePath, String localPath) {
        try {
            File localFile = new File(localPath);
            if (!localFile.getParentFile().exists()) {
                localFile.getParentFile().mkdirs();
            }
            if(localFile.isDirectory()){
                String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
                log.info("未配置文件名，使用默认文件名：{}",fileName);
                localPath = localPath.concat(File.separator).concat(fileName);
            }
            Map<String, Object> params = new HashMap<>();
            params.put("appName", fYunFileConfig.getKey());
            params.put("secret", fYunFileConfig.getSecret());
            params.put("fileName", remoteFilePath);
            params.put("targetPath", localPath);
            String url = fYunFileConfig.getEndPoint() + httpFyunConfig.getDownloadFile();
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, params, Result.class);
            log.info("Fyun Http Utils file exist，url:{},params:{},结果,{}", url, JSONObject.toJSONString(params), JSONObject.toJSONString(responseEntity.getBody()));
            if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody().getCode() != Result.CODE_SUCCESS) {
                log.error("Fyun Http Utils copy file failed!");
            }
        } catch (Throwable throwable) {
            log.error("文件下载失败：{}", remoteFilePath);
            throwable.printStackTrace();
        }
    }

    @Override
    public URL getPresignedUrl(String bucket, String url) {
        throw new UnsupportedOperationException("不支持此操作！");
    }

    @Override
    public long getSubFileNums(String bucket, String url) {
        return 0;
    }

    @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 void restoreFolder(String bucket, String folderName, Integer priority) {

    }

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

    }

    @Override
    public Long getSpace(String bucket, String key) {
        return null;
    }

}
