package cn.meowrain.aioj.backend.fileservice.storage.impl;

import cn.meowrain.aioj.backend.fileservice.storage.FileStorageStrategy;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

/**
 * 腾讯云COS文件存储策略
 *
 * @author meowrain
 * @since 2026-01-10
 */
@Slf4j
@Component("cosFileStorageStrategy")
@ConditionalOnProperty(prefix = "file-config.cos", name = "enabled", havingValue = "true")
public class CosFileStorageStrategy implements FileStorageStrategy {

    @Value("${file-config.cos.secret-id}")
    private String secretId;

    @Value("${file-config.cos.secret-key}")
    private String secretKey;

    @Value("${file-config.cos.region}")
    private String region;

    @Value("${file-config.cos.bucket-name}")
    private String bucketName;

    @Value("${file-config.cos.domain:}")
    private String domain;

    @Value("${file-config.cos.prefix:}")
    private String prefix;

    @Value("${file-config.cos.presigned-url-expire-seconds:3600}")
    private Integer presignedUrlExpireSeconds;

    private COSClient cosClient;

    @PostConstruct
    public void init() {
        try {
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            ClientConfig clientConfig = new ClientConfig(new Region(region));
            cosClient = new COSClient(cred, clientConfig);
            log.info("腾讯云COS存储初始化成功, bucket: {}, region: {}", bucketName, region);
        } catch (Exception e) {
            log.error("腾讯云COS存储初始化失败", e);
            throw new RuntimeException("初始化腾讯云COS存储失败", e);
        }
    }

    @PreDestroy
    public void destroy() {
        if (cosClient != null) {
            cosClient.shutdown();
            log.info("腾讯云COS客户端已关闭");
        }
    }

    @Override
    public String upload(org.springframework.web.multipart.MultipartFile file, String filePath) throws IOException {
        try {
            String key = buildKey(filePath);
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());

            PutObjectRequest request = new PutObjectRequest(bucketName, key, file.getInputStream(), metadata);
            cosClient.putObject(request);

            log.info("文件上传到COS成功: {}", key);
            return getFileUrl(filePath);
        } catch (Exception e) {
            log.error("文件上传到COS失败: {}", filePath, e);
            throw new IOException("文件上传到COS失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String upload(InputStream inputStream, String filePath, long fileSize) throws IOException {
        try {
            String key = buildKey(filePath);
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(fileSize);

            PutObjectRequest request = new PutObjectRequest(bucketName, key, inputStream, metadata);
            cosClient.putObject(request);

            log.info("文件流上传到COS成功: {}", key);
            return getFileUrl(filePath);
        } catch (Exception e) {
            log.error("文件流上传到COS失败: {}", filePath, e);
            throw new IOException("文件流上传到COS失败: " + e.getMessage(), e);
        }
    }

    @Override
    public boolean delete(String filePath) {
        try {
            String key = buildKey(filePath);
            cosClient.deleteObject(bucketName, key);
            log.info("文件从COS删除成功: {}", key);
            return true;
        } catch (Exception e) {
            log.error("文件从COS删除失败: {}", filePath, e);
            return false;
        }
    }

    @Override
    public boolean exists(String filePath) {
        try {
            String key = buildKey(filePath);
            return cosClient.doesObjectExist(bucketName, key);
        } catch (Exception e) {
            log.error("检查文件是否存在失败: {}", filePath, e);
            return false;
        }
    }

    @Override
    public String getFileUrl(String filePath) {
        String key = buildKey(filePath);

        if (domain != null && !domain.isEmpty()) {
            return domain + "/" + key;
        }

        Date expirationDate = new Date(System.currentTimeMillis() + presignedUrlExpireSeconds * 1000L);
        URL url = cosClient.generatePresignedUrl(bucketName, key, expirationDate, HttpMethodName.GET);
        return url.toString();
    }

    @Override
    public String getStorageType() {
        return "COS";
    }

    private String buildKey(String filePath) {
        if (prefix != null && !prefix.isEmpty()) {
            return prefix + "/" + filePath;
        }
        return filePath;
    }
}
