package shop.alien.util.ali;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import shop.alien.util.file.FileUtil;

import java.io.File;
import java.io.InputStream;

/**
 * 阿里云oss工具类
 *
 * @author ssk
 * @version 1.0
 * @date 2025/7/17 8:51
 */
@Slf4j
@Component
@RefreshScope
public class AliOSSUtil {

    @Value("${ali.oss.accessKeyId}")
    private String accessKeyId;

    @Value("${ali.oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${ali.oss.endPoint}")
    private String endPoint;

    @Value("${ali.oss.bucketName}")
    private String bucketName;

    /**
     * oss上传文件
     *
     * @param multipartFile 前端上传的文件
     * @param ossFilePath   oss中文件全路径(image/xxx.jpg)
     * @return filePath
     */
    public String uploadFile(MultipartFile multipartFile, String ossFilePath) {
        // 验证参数
        if (multipartFile == null || multipartFile.isEmpty()) {
            log.error("AliOSSUtil.uploadFile ERROR: multipartFile is null or empty");
            return null;
        }
        
        if (StringUtils.isEmpty(ossFilePath)) {
            log.error("AliOSSUtil.uploadFile ERROR: ossFilePath is empty");
            return null;
        }
        
        File convertFile = FileUtil.convert(multipartFile);
        if (convertFile == null) {
            log.error("AliOSSUtil.uploadFile ERROR: convertFile is null");
            return null;
        }
        
        return uploadFile(convertFile, ossFilePath);
    }

    /**
     * oss上传文件
     *
     * @param file        后端文件
     * @param ossFilePath oss中文件全路径(image/xxx.jpg)
     * @return filePath
     */
    public String uploadFile(File file, String ossFilePath) {
        // 验证参数
        if (file == null) {
            log.error("AliOSSUtil.uploadFile ERROR: file is null");
            return null;
        }
        
        if (StringUtils.isEmpty(ossFilePath)) {
            log.error("AliOSSUtil.uploadFile ERROR: ossFilePath is empty");
            return null;
        }
        
        // 检查文件是否存在且不为空
        if (!file.exists()) {
            log.error("AliOSSUtil.uploadFile ERROR: file does not exist, path: {}", file.getAbsolutePath());
            return null;
        }
        
        if (file.length() == 0) {
            log.error("AliOSSUtil.uploadFile ERROR: file is empty, path: {}", file.getAbsolutePath());
            return null;
        }
        
        // 验证ossFilePath格式 - 不能以/开头
        if (ossFilePath.startsWith("/")) {
            log.error("AliOSSUtil.uploadFile ERROR: ossFilePath cannot start with '/': {}", ossFilePath);
            return null;
        }
        
        if (ossFilePath.contains("..") || ossFilePath.contains("\\")) {
            log.error("AliOSSUtil.uploadFile ERROR: invalid ossFilePath format: {}", ossFilePath);
            return null;
        }

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossFilePath, file);
            // 上传文件
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            String eTag = result.getETag();
            if (StringUtils.isNotEmpty(eTag)) {
                //删除临时文件
                file.delete();
                return "https://" + bucketName + "." + endPoint + "/" + ossFilePath;
            }
            return null;
        } catch (Exception e) {
            log.error("AliOSSUtil.uploadFile ERROR: {}", e.getMessage(), e);
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * oss上传文件（从输入流）
     *
     * @param inputStream 输入流
     * @param ossFilePath oss中文件全路径(image/xxx.jpg)
     * @return filePath
     */
    public String uploadFile(InputStream inputStream, String ossFilePath) {
        // 验证参数
        if (inputStream == null) {
            log.error("AliOSSUtil.uploadFile ERROR: inputStream is null");
            return null;
        }
        
        if (StringUtils.isEmpty(ossFilePath)) {
            log.error("AliOSSUtil.uploadFile ERROR: ossFilePath is empty");
            return null;
        }
        
        // 验证ossFilePath格式 - 不能以/开头
        if (ossFilePath.startsWith("/")) {
            log.error("AliOSSUtil.uploadFile ERROR: ossFilePath cannot start with '/': {}", ossFilePath);
            return null;
        }
        
        if (ossFilePath.contains("..") || ossFilePath.contains("\\")) {
            log.error("AliOSSUtil.uploadFile ERROR: invalid ossFilePath format: {}", ossFilePath);
            return null;
        }

        // 创建OSSClient实例
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        try {
            // 创建PutObjectRequest对象（使用输入流）
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossFilePath, inputStream);
            // 上传文件
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            String eTag = result.getETag();
            if (StringUtils.isNotEmpty(eTag)) {
                return "https://" + bucketName + "." + endPoint + "/" + ossFilePath;
            }
            return null;
        } catch (Exception e) {
            log.error("AliOSSUtil.uploadFile ERROR: {}", e.getMessage(), e);
            return null;
        } finally {
            // 关闭输入流
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e) {
                    log.warn("AliOSSUtil.uploadFile WARN: 关闭输入流失败: {}", e.getMessage());
                }
            }
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

}