package com.erp.file.service.storage;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
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.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 阿里云OSS存储策略
 */
@Slf4j
@Component
public class OssStorageStrategy implements StorageStrategy {
    
    @Value("${file.storage.oss.endpoint:}")
    private String endpoint;
    
    @Value("${file.storage.oss.access-key-id:}")
    private String accessKeyId;
    
    @Value("${file.storage.oss.access-key-secret:}")
    private String accessKeySecret;
    
    @Value("${file.storage.oss.bucket-name:}")
    private String bucketName;
    
    @Value("${file.storage.oss.base-url:}")
    private String baseUrl;
    
    @Value("${file.storage.oss.custom-domain:}")
    private String customDomain;
    
    private OSS ossClient;
    
    @PostConstruct
    @Override
    public void init() {
        if (!isConfigured()) {
            log.warn("阿里云OSS未配置，将不启用该存储策略");
            return;
        }
        this.ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        log.info("阿里云OSS存储初始化成功，桶: {}", bucketName);
    }
    
    @Override
    public String upload(MultipartFile file, String path, String storageName) {
        ensureClient();
        try {
            String objectName = path + "/" + storageName;
            
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file.getInputStream());
            putObjectRequest.setMetadata(new ObjectMetadata());
            putObjectRequest.getMetadata().setContentType(file.getContentType());
            
            ossClient.putObject(putObjectRequest);
            
            log.info("文件上传至OSS成功: {}", objectName);
            return getUrl(objectName);
        } catch (IOException e) {
            throw new RuntimeException("OSS文件上传失败", e);
        }
    }
    
    @Override
    public InputStream download(String path) {
        ensureClient();
        try {
            OSSObject ossObject = ossClient.getObject(bucketName, path);
            return ossObject.getObjectContent();
        } catch (Exception e) {
            throw new RuntimeException("OSS文件下载失败", e);
        }
    }
    
    @Override
    public void delete(String path) {
        ensureClient();
        try {
            ossClient.deleteObject(bucketName, path);
            log.info("OSS文件删除成功: {}", path);
        } catch (Exception e) {
            log.error("OSS文件删除失败: {}", path, e);
            throw new RuntimeException("OSS文件删除失败", e);
        }
    }
    
    @Override
    public boolean exists(String path) {
        ensureClient();
        try {
            return ossClient.doesObjectExist(bucketName, path);
        } catch (Exception e) {
            log.error("检查OSS文件是否存在失败: {}", path, e);
            return false;
        }
    }
    
    @Override
    public String getUrl(String path) {
        if (customDomain != null && !customDomain.isEmpty()) {
            return customDomain + "/" + path;
        }
        if (baseUrl != null && !baseUrl.isEmpty()) {
            return baseUrl + "/" + path;
        }
        // 生成带过期时间的签名URL
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
            LocalDateTime expiration = LocalDateTime.now().plusDays(365);
            URL url = ossClient.generatePresignedUrl(bucketName, path, java.sql.Timestamp.valueOf(expiration));
            return url.toString();
        } catch (Exception e) {
            log.error("生成OSS URL失败", e);
            return path;
        }
    }
    
    @Override
    public String getFullPath(String path) {
        return bucketName + "/" + path;
    }
    
    @Override
    public String getType() {
        return "oss";
    }
    
    private void ensureClient() {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未初始化，请检查配置");
        }
    }
    
    private boolean isConfigured() {
        return endpoint != null && !endpoint.isEmpty() &&
               accessKeyId != null && !accessKeyId.isEmpty() &&
               accessKeySecret != null && !accessKeySecret.isEmpty() &&
               bucketName != null && !bucketName.isEmpty();
    }
}
