package com.ruoyi.common.utils;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;

@Component
public class TencentCosUtil {
    // 设置好账号的ACCESS_KEY和SECRET_KEY
    @Value("${tencentCos.accessKey}")
    private String ACCESS_KEY;
    @Value("${tencentCos.secretKey}")
    private String SECRET_KEY;
    // 要上传的空间（创建空间的名称）
    @Value("${tencentCos.bucketName}")
    private String bucketName;
    @Value("${tencentCos.endpoint}")
    private String endpoint;
    // 使用的是测试域名
    @Value("${tencentCos.domain}")
    private String domain;


    /**
     * 上传MultipartFile到腾讯云COS，返回文件访问地址
     * 与AwsS3Util.uploadMultipartFile方法接口兼容
     */
    public String upload(MultipartFile file) throws Exception {
        return uploadMultipartFile(file, true);
    }

    /**
     * 上传MultipartFile到腾讯云COS，返回文件访问地址
     *
     * @param file     前端上传的MultipartFile
     * @param isPublic 是否公开访问（当前实现中忽略，使用domain配置）
     * @return 文件访问地址（URL字符串）
     */
    public String uploadMultipartFile(MultipartFile file, boolean isPublic) throws Exception {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        COSClient cosClient = createCosClient();

        // 生成唯一文件键，格式与AWS一致：yyyy/MM/dd/uuid_filename
        String key = generateCosKey(file.getOriginalFilename());

        try {
            InputStream inputStream = file.getInputStream();
            ObjectMetadata objectMetadata = new ObjectMetadata();
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    bucketName,
                    key,
                    inputStream,
                    objectMetadata);

            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);

            // 返回COS文件访问地址
            String url = domain + (domain.endsWith("/") ? "" : "/") + key;
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("上传文件到COS失败: " + e.getMessage(), e);
        } finally {
            cosClient.shutdown();
        }
    }

    /**
     * 通过URL下载文件并上传到COS
     * 与AwsS3Util.uploadFileByUrl方法接口兼容
     */
    public String uploadFileByUrl(String fileUrl) throws Exception {
        return uploadFileByUrl(fileUrl, true);
    }

    public String uploadFileByUrl(String fileUrl, boolean isPublic) throws Exception {
        if (fileUrl == null || fileUrl.trim().isEmpty()) {
            throw new IllegalArgumentException("文件下载链接不能为空");
        }

        Path tempPath = downloadFileToTemp(fileUrl);
        try {
            // 使用临时文件上传
            MultipartFile multipartFile = createMultipartFileFromPath(tempPath, extractFileNameFromUrl(fileUrl));
            return uploadMultipartFile(multipartFile, isPublic);
        } finally {
            Files.deleteIfExists(tempPath);
        }
    }


    private COSClient createCosClient() {
        //1.1 初始化用户身份信息
        BasicCOSCredentials credentials = new BasicCOSCredentials(ACCESS_KEY, SECRET_KEY);
        //1.2 设置bucket的地域
        Region region = new Region(endpoint);
        ClientConfig clientConfig = new ClientConfig(region);
        // 这里建议设置使用 https 协议
        clientConfig.setHttpProtocol(HttpProtocol.https);
        clientConfig.setConnectionTimeout(30 * 1000); // 连接超时30秒
        clientConfig.setSocketTimeout(60 * 1000);    // 读取超时60秒
        //1.3 生成cos客户端
        return new COSClient(credentials, clientConfig);
    }

    /**
     * 生成COS文件键，与AWS保持一致的命名格式
     */
    private String generateCosKey(String originalFileName) {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
        String dateTime = new DateTime().toString("yyyy/MM/dd");
        return dateTime + "/" + uuid + "_" + originalFileName;
    }

    /**
     * 下载文件到临时路径
     */
    private Path downloadFileToTemp(String fileUrl) throws Exception {
        String suffix = getFileSuffixFromUrl(fileUrl);
        Path tempPath = Files.createTempFile("url-upload-", suffix);

        HttpURLConnection connection = null;
        InputStream in = null;
        OutputStream out = null;

        try {
            URL url = new URL(fileUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(10000);

            int responseCode = connection.getResponseCode();
            if (responseCode < 200 || responseCode >= 300) {
                throw new RuntimeException("文件下载失败，状态码：" + responseCode);
            }

            in = connection.getInputStream();
            out = Files.newOutputStream(tempPath);

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        } finally {
            if (out != null) {
                try { out.close(); } catch (IOException e) { e.printStackTrace(); }
            }
            if (in != null) {
                try { in.close(); } catch (IOException e) { e.printStackTrace(); }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }

        return tempPath;
    }

    private String extractFileNameFromUrl(String fileUrl) {
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        if (fileName.contains("?")) {
            fileName = fileName.split("\\?")[0];
        }
        return fileName.isEmpty() ? "default_file" : fileName;
    }

    private String getFileSuffixFromUrl(String fileUrl) {
        String fileName = extractFileNameFromUrl(fileUrl);
        if (fileName.contains(".")) {
            return fileName.substring(fileName.lastIndexOf("."));
        }
        return ".tmp";
    }

    /**
     * 将Path转换为MultipartFile（简单实现，用于uploadFileByUrl）
     */
    private MultipartFile createMultipartFileFromPath(Path path, String originalFilename) throws IOException {
        byte[] bytes = Files.readAllBytes(path);
        return new MultipartFile() {
            @Override
            public String getName() { return "file"; }
            @Override
            public String getOriginalFilename() { return originalFilename; }
            @Override
            public String getContentType() { return null; }
            @Override
            public boolean isEmpty() { return bytes.length == 0; }
            @Override
            public long getSize() { return bytes.length; }
            @Override
            public byte[] getBytes() throws IOException { return bytes; }
            @Override
            public InputStream getInputStream() throws IOException { return Files.newInputStream(path); }
            @Override
            public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
                Files.copy(path, dest.toPath());
            }
        };
    }
}
