package com.moka.gdtauto.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectRequest;
import com.moka.gdtauto.config.AliyunOssConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * 阿里云OSS工具类
 * 提供文件上传、删除等功能
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class OssUtil {
    
    private final OSS ossClient;
    private final AliyunOssConfig ossConfig;
    
    /**
     * 上传文件（File对象）
     * 
     * @param file 文件对象
     * @param folder 存储文件夹路径（如：images/、videos/）
     * @return 文件访问URL（CDN域名）
     */
    public String uploadFile(File file, String folder) {
        String fileName = generateFileName(file.getName(), folder);
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(), 
                    fileName, 
                    file
            );
            ossClient.putObject(putObjectRequest);
            log.info("文件上传成功：{}", fileName);
            return getFileUrl(fileName);
        } catch (Exception e) {
            log.error("文件上传失败：{}", fileName, e);
            throw new RuntimeException("文件上传失败", e);
        }
    }
    
    /**
     * 上传文件（MultipartFile对象）
     * 
     * @param file MultipartFile文件对象
     * @param folder 存储文件夹路径（如：images/、videos/）
     * @return 文件访问URL（CDN域名）
     */
    public String uploadFile(MultipartFile file, String folder) {
        String fileName = generateFileName(file.getOriginalFilename(), folder);
        try (InputStream inputStream = file.getInputStream()) {
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(), 
                    fileName, 
                    inputStream
            );
            ossClient.putObject(putObjectRequest);
            log.info("文件上传成功：{}", fileName);
            return getFileUrl(fileName);
        } catch (IOException e) {
            log.error("文件上传失败：{}", fileName, e);
            throw new RuntimeException("文件上传失败", e);
        }
    }
    
    /**
     * 上传文件（InputStream流）
     * 
     * @param inputStream 文件输入流
     * @param originalFileName 原始文件名
     * @param folder 存储文件夹路径（如：images/、videos/）
     * @return 文件访问URL（CDN域名）
     */
    public String uploadFile(InputStream inputStream, String originalFileName, String folder) {
        String fileName = generateFileName(originalFileName, folder);
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(), 
                    fileName, 
                    inputStream
            );
            ossClient.putObject(putObjectRequest);
            log.info("文件上传成功：{}", fileName);
            return getFileUrl(fileName);
        } catch (Exception e) {
            log.error("文件上传失败：{}", fileName, e);
            throw new RuntimeException("文件上传失败", e);
        }
    }
    
    /**
     * 上传字节数组
     * 
     * @param bytes 字节数组
     * @param originalFileName 原始文件名
     * @param folder 存储文件夹路径（如：images/、videos/）
     * @return 文件访问URL（CDN域名）
     */
    public String uploadFile(byte[] bytes, String originalFileName, String folder) {
        String fileName = generateFileName(originalFileName, folder);
        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    ossConfig.getBucketName(), 
                    fileName, 
                    inputStream
            );
            ossClient.putObject(putObjectRequest);
            log.info("文件上传成功：{}", fileName);
            return getFileUrl(fileName);
        } catch (Exception e) {
            log.error("文件上传失败：{}", fileName, e);
            throw new RuntimeException("文件上传失败", e);
        }
    }
    
    /**
     * 删除文件
     * 
     * @param fileUrl 文件URL（可以是完整URL或OSS对象Key）
     * @return 是否删除成功
     */
    public boolean deleteFile(String fileUrl) {
        try {
            String objectKey = extractObjectKey(fileUrl);
            ossClient.deleteObject(ossConfig.getBucketName(), objectKey);
            log.info("文件删除成功：{}", objectKey);
            return true;
        } catch (Exception e) {
            log.error("文件删除失败：{}", fileUrl, e);
            return false;
        }
    }
    
    /**
     * 批量删除文件
     * 
     * @param fileUrls 文件URL数组
     * @return 是否全部删除成功
     */
    public boolean deleteFiles(String... fileUrls) {
        boolean allSuccess = true;
        for (String fileUrl : fileUrls) {
            if (!deleteFile(fileUrl)) {
                allSuccess = false;
            }
        }
        return allSuccess;
    }
    
    /**
     * 判断文件是否存在
     * 
     * @param fileUrl 文件URL（可以是完整URL或OSS对象Key）
     * @return 是否存在
     */
    public boolean fileExists(String fileUrl) {
        try {
            String objectKey = extractObjectKey(fileUrl);
            return ossClient.doesObjectExist(ossConfig.getBucketName(), objectKey);
        } catch (Exception e) {
            log.error("检查文件是否存在失败：{}", fileUrl, e);
            return false;
        }
    }
    
    /**
     * 生成唯一文件名
     * 
     * @param originalFileName 原始文件名
     * @param folder 文件夹路径
     * @return 生成的唯一文件名（含路径）
     */
    private String generateFileName(String originalFileName, String folder) {
        String suffix = "";
        if (originalFileName != null && originalFileName.contains(".")) {
            suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
        }
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String folderPath = (folder == null || folder.isEmpty()) ? "" : 
                           (folder.endsWith("/") ? folder : folder + "/");
        return folderPath + uuid + suffix;
    }
    
    /**
     * 获取文件访问URL（使用CDN域名）
     * 
     * @param objectKey OSS对象Key
     * @return 完整的文件访问URL
     */
    private String getFileUrl(String objectKey) {
        String cdnDomain = ossConfig.getCdnDomain();
        if (cdnDomain != null && !cdnDomain.isEmpty()) {
            return cdnDomain + "/" + objectKey;
        }
        // 如果没有配置CDN域名，使用OSS默认域名
        return "https://" + ossConfig.getBucketName() + "." + 
               ossConfig.getEndpoint() + "/" + objectKey;
    }
    
    /**
     * 从URL中提取OSS对象Key
     * 
     * @param fileUrl 文件URL
     * @return OSS对象Key
     */
    private String extractObjectKey(String fileUrl) {
        if (fileUrl == null || fileUrl.isEmpty()) {
            throw new IllegalArgumentException("文件URL不能为空");
        }
        
        // 如果是完整URL，提取对象Key
        if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
            int lastSlashIndex = fileUrl.indexOf("/", 8); // 跳过协议部分
            if (lastSlashIndex != -1 && lastSlashIndex < fileUrl.length() - 1) {
                return fileUrl.substring(lastSlashIndex + 1);
            }
        }
        
        // 否则认为就是对象Key
        return fileUrl;
    }
}
