package com.njcn.product.event.transientes.utils;

import cn.hutool.core.lang.UUID;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

/**
 * @Author: cdf
 * @CreateTime: 2025-10-21
 * @Description:
 */
@Component
@Slf4j
public class OssFileStorageUtils {


    @Value("${aliyun.oss.endpoint}")
    private String endpoint="oss-cn-beijing.aliyuncs.com";

    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId="LTAI5tQYuyu1PpiCdeM74PT6";

    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret="vTGHcQOCF9u7w9FL3HAHJO1oufVWru";

    @Value("${aliyun.oss.bucketName}")
    private String bucketName= "cn-comtrade";

    @Value("${aliyun.oss.basePath:pqmm}")
    private String basePath;


    private OSS ossClient;

    @PostConstruct
    public void init() {
        // 初始化 OSS 客户端
        this.ossClient = new OSSClientBuilder().build(
                endpoint,
                accessKeyId,
                accessKeySecret
        );
    }

    /**
     * 将对象直接以JSON流的形式上传到OSS
     *
     * @param object     要上传的Java对象
     * @param objectName 在OSS上保存的路径和文件名 (例如: "data/user001.json")
     * @throws IOException
     */
    public void uploadObjectAsJsonStream(Object object, String objectName) throws IOException {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 使用try-with-resources确保ByteArrayInputStream被关闭
        ByteArrayInputStream inputStream = convertObjectToJsonStream(object);
        try {
            // 创建上传请求。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, basePath+objectName, inputStream);
            // 可选：设置对象元信息，如Content-Type
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setContentType("application/json");
            // putObjectRequest.setMetadata(metadata);

            // 执行上传。
            ossClient.putObject(putObjectRequest);
            System.out.println("JSON对象已直接上传至OSS: " + objectName);
        } finally {
            inputStream.close();

        }
    }

    /**
     * 上传本地文件到阿里云OSS
     *
     * @param localFilePath 本地文件的完整路径
     * @return 文件在OSS上的访问URL
     */
    public String uploadLocalFile(String localFilePath,String targetPath) {
        File file = new File(localFilePath);
        if (!file.exists()) {
            log.info("本地波形文件不存在"+localFilePath );
            return null;
        }
        // 生成唯一的文件名，防止覆盖:cite[5]:cite[8]
        String originalFileName = file.getName();
        originalFileName = basePath+targetPath+"/"+originalFileName;

        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, originalFileName, file);
            // 执行上传
            ossClient.putObject(putObjectRequest);
            // 生成文件的访问URL:cite[7]:cite[8]
            String fileUrl = "https://" + bucketName + "." + endpoint + "/" + originalFileName;
            log.info("文件上传成功，访问地址: {}", fileUrl);
            return fileUrl;
        } catch (OSSException oe) {
            log.error("OSS服务异常: {}", oe.getErrorMessage());
        } catch (Exception e) {
            log.error("文件上传失败: ", e);
        }
        // 在实际项目中，可以考虑抛出自定义异常
        return null;
    }

    /**
     * 将Java对象序列化为JSON字节流
     *
     * @param object Java对象
     * @return 包含JSON数据的ByteArrayInputStream
     * @throws IOException
     */
    private ByteArrayInputStream convertObjectToJsonStream(Object object) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        // 将对象序列化为JSON字节数组
        byte[] jsonBytes = objectMapper.writeValueAsBytes(object);
        // 返回字节数组输入流
        return new ByteArrayInputStream(jsonBytes);
    }


    /**
     * 上传文件流到OSS
     *
     * @param inputStream 文件输入流
     * @param fileName    文件名
     * @param contentType 文件类型
     * @return 文件访问URL
     */
    public String uploadFileStream(InputStream inputStream, String fileName, String contentType) {
        if (inputStream == null) {
            throw new IllegalArgumentException("文件输入流不能为空");
        }

        if (fileName == null || fileName.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }

        try {
            // 生成唯一文件名
            String fileExtension = getFileExtension(fileName);
            String uniqueFileName = UUID.randomUUID().toString() + fileExtension;

            // 构建文件路径
            String filePath = basePath + "/" + uniqueFileName;

            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream);

            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(contentType);
            putObjectRequest.setMetadata(metadata);

            // 执行上传
            PutObjectResult result = ossClient.putObject(putObjectRequest);

            // 关闭输入流
            inputStream.close();

            // 返回文件访问URL
            return getFileUrl(filePath);

        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }


    /**
     * 上传文件到OSS
     *
     * @param file 上传的文件
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        try {
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = getFileExtension(originalFilename);
            String uniqueFileName = UUID.randomUUID() + fileExtension;

            // 构建文件路径
            String filePath = basePath + "/" + uniqueFileName;

            // 上传文件
            InputStream inputStream = file.getInputStream();
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream);

            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());
            putObjectRequest.setMetadata(metadata);

            // 执行上传
            PutObjectResult result = ossClient.putObject(putObjectRequest);

            // 关闭输入流
            inputStream.close();

            // 返回文件访问URL
            return getFileUrl(filePath);

        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }

    /**
     * 上传文件到指定目录
     *
     * @param file      上传的文件
     * @param directory 目录路径
     * @return 文件访问URL
     */
    public String uploadFileToDirectory(MultipartFile file, String directory) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        if (directory == null || directory.trim().isEmpty()) {
            throw new IllegalArgumentException("目录路径不能为空");
        }

        try {
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = getFileExtension(originalFilename);
            String uniqueFileName = UUID.randomUUID().toString() + fileExtension;

            // 构建文件路径
            String filePath = directory + "/" + uniqueFileName;

            // 上传文件
            InputStream inputStream = file.getInputStream();
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream);

            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());
            putObjectRequest.setMetadata(metadata);

            // 执行上传
            PutObjectResult result = ossClient.putObject(putObjectRequest);

            // 关闭输入流
            inputStream.close();

            // 返回文件访问URL
            return getFileUrl(filePath);

        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }


    /**
     * 删除OSS上的文件
     *
     * @param fileUrl 文件URL
     * @return 是否删除成功
     */
    public boolean deleteFile(String fileUrl) {
        if (fileUrl == null || fileUrl.trim().isEmpty()) {
            throw new IllegalArgumentException("文件URL不能为空");
        }

        try {
            // 从URL中提取文件路径
            String filePath = extractFilePathFromUrl(fileUrl);

            // 检查文件是否存在
            if (ossClient.doesObjectExist(bucketName, filePath)) {
                // 删除文件
                ossClient.deleteObject(bucketName, filePath);
                return true;
            }
            return false;

        } catch (Exception e) {
            throw new RuntimeException("文件删除失败", e);
        }
    }

    /**
     * 获取文件访问URL
     *
     * @param filePath 文件路径
     * @return 文件访问URL
     */
    public String getFileUrl(String filePath) {
        if (filePath == null || filePath.trim().isEmpty()) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        // 构建文件URL
        return "https://" + bucketName + "." + endpoint + "/" + filePath;
    }

    /**
     * 获取带签名的临时URL（默认1小时有效期）
     *
     * @param filePath 文件路径
     * @return 带签名的临时URL
     */
    public String getSignedUrl(String filePath) {
        return getSignedUrl(filePath, 3600);
    }

    /**
     * 获取带签名的临时URL
     *
     * @param filePath          文件路径
     * @param expirationSeconds 过期时间（秒）
     * @return 带签名的临时URL
     */
    public String getSignedUrl(String filePath, int expirationSeconds) {
        if (filePath == null || filePath.trim().isEmpty()) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        if (expirationSeconds <= 0) {
            throw new IllegalArgumentException("过期时间必须大于0");
        }

        try {
            // 设置URL过期时间
            Date expiration = new Date(System.currentTimeMillis() + expirationSeconds * 1000L);

            // 生成签名URL
            URL url = ossClient.generatePresignedUrl(bucketName, filePath, expiration);

            return url.toString();

        } catch (Exception e) {
            throw new RuntimeException("生成签名URL失败", e);
        }
    }

    /**
     * 获取文件信息
     *
     * @param filePath 文件路径
     * @return 文件信息
     */
    public ObjectMetadata getFileMetadata(String filePath) {
        if (filePath == null || filePath.trim().isEmpty()) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        try {
            return ossClient.getObjectMetadata(bucketName, filePath);
        } catch (Exception e) {
            throw new RuntimeException("获取文件信息失败", e);
        }
    }

    /**
     * 检查文件是否存在
     *
     * @param filePath 文件路径
     * @return 是否存在
     */
    public boolean doesFileExist(String filePath) {
        if (filePath == null || filePath.trim().isEmpty()) {
            return false;
        }

        try {
            return ossClient.doesObjectExist(bucketName, filePath);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 下载文件
     *
     * @param filePath 文件路径
     * @return 文件输入流
     */
    public InputStream downloadFile(String filePath) {
        if (filePath == null || filePath.trim().isEmpty()) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        try {
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, filePath);
            OSSObject ossObject = ossClient.getObject(getObjectRequest);
            return ossObject.getObjectContent();
        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }

    /**
     * 创建目录
     *
     * @param directoryPath 目录路径
     */
    public void createDirectory(String directoryPath) {
        if (directoryPath == null || directoryPath.trim().isEmpty()) {
            throw new IllegalArgumentException("目录路径不能为空");
        }

        try {
            // 目录必须以"/"结尾
            String normalizedPath = directoryPath.endsWith("/") ? directoryPath : directoryPath + "/";

            // 创建目录
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(0);
            InputStream emptyContent = new ByteArrayInputStream(new byte[0]);
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, normalizedPath, emptyContent, metadata);
            ossClient.putObject(putObjectRequest);

        } catch (Exception e) {
            throw new RuntimeException("创建目录失败", e);
        }
    }


    /**
     * 获取文件扩展名
     *
     * @param fileName 文件名
     * @return 文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || fileName.isEmpty()) {
            return "";
        }
        int lastIndexOfDot = fileName.lastIndexOf(".");
        if (lastIndexOfDot == -1) {
            return "";
        }
        return fileName.substring(lastIndexOfDot);
    }

    /**
     * 从URL中提取文件路径
     *
     * @param fileUrl 文件URL
     * @return 文件路径
     */
    private String extractFilePathFromUrl(String fileUrl) {
        String prefix = "https://" + bucketName + "." + endpoint + "/";
        if (fileUrl.startsWith(prefix)) {
            return fileUrl.substring(prefix.length());
        }
        return fileUrl;
    }


}


