package com.fdkankan.filestorage;

import cn.hutool.core.util.ObjectUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.fdkankan.filestorage.aliyun.AliyunOssTemplate;
import com.fdkankan.filestorage.aws.AwsTemplate;
import com.fdkankan.filestorage.cos.CosTemplate;
import com.fdkankan.filestorage.minio.MinioTemplate;
import com.fdkankan.filestorage.properties.*;
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.HttpProtocol;
import com.qcloud.cos.region.Region;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Xiewj
 * @date 2023/8/28
 */
@Configuration
@ConditionalOnProperty(prefix  = "filestorage",name= "active")
@Slf4j
public class StorageAutoConfiguration {

    @Bean
    @ConditionalOnProperty(prefix  = "filestorage",name= "active")
    FileStroageProperties fileStroageProperties(){
        return new FileStroageProperties();
    }

    @Bean
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "oss")
    public AliyunOssProperties aliyunOssProperties(FileStroageProperties fileStroageProperties){
        AliyunOssProperties aliyunOssProperties = new AliyunOssProperties();
        aliyunOssProperties .setActive(fileStroageProperties.getActive());
        return aliyunOssProperties;
    }

    @Bean(name = "aliyunOssClient")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "oss")
    public OSS aliyunOssClient(AliyunOssProperties properties) {
        return new OSSClientBuilder().build(properties.getRequestEndpoint(),
                properties.getAccessKey(),
                properties.getAccessKeySecret(),
                properties.getConfig());
    }
    @Bean(name = "aliyunOssTemplate")
    @Qualifier("oss")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "oss")
    public FileStorageTemplate aliyunOssTemplate(OSS oss, AliyunOssProperties properties) {
        return new  AliyunOssTemplate(oss, properties);
    }


    @Bean
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "aws")
    public AwsProperties awsProperties(FileStroageProperties fileStroageProperties){
        AwsProperties awsProperties = new AwsProperties();
        awsProperties.setActive(fileStroageProperties.getActive());
        return awsProperties;
    }


    @Bean(name = "amazonS3Client")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "aws")
    public AmazonS3 amazonS3Client(AwsProperties properties) {
        BasicAWSCredentials awsCreds = new BasicAWSCredentials(properties.getAccessKey(), properties.getAccessKeySecret());
        ClientConfiguration clientConfiguration = new ClientConfiguration();
        clientConfiguration.setMaxErrorRetry(5);
        clientConfiguration.setMaxConnections(300);
        clientConfiguration.setConnectionTimeout(5000);
        clientConfiguration.setSocketTimeout(5000);
        Regions regions = Regions.EU_WEST_2;
        if (ObjectUtil.isNotEmpty(properties.getRegion())){
            regions=Regions.fromName(properties.getRegion());
        }
        AmazonS3 s3 = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .withRegion(regions)
                .withClientConfiguration(clientConfiguration)
                .build();
        return s3;
    }



    @Bean(name = "AwsOssTemplate")
    @Qualifier("aws")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "aws")
    public FileStorageTemplate AwsOssTemplate(AmazonS3 oss, AwsProperties properties) {
        return new AwsTemplate(oss, properties);
    }


    @Bean
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "cos")
    public CosProperties cosProperties(FileStroageProperties fileStroageProperties) {
        CosProperties cosProperties = new CosProperties();
        cosProperties.setActive(fileStroageProperties.getActive());
        return cosProperties;
    }


    @Bean(name = "cosClient")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "cos")
    public COSClient cosClient(CosProperties properties) {

        // 1 初始化用户身份信息（secretId, secretKey）。
        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
        COSCredentials cred = new BasicCOSCredentials(properties.getAccessKey(), properties.getAccessKeySecret());
        // 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        Region region = new Region(properties.getRegionId());
        ClientConfig clientConfig = properties.getConfig();
        clientConfig.setRegion(region);
        // 这里建议设置使用 https 协议
        // 从 5.6.54 版本开始，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端。
        COSClient cosClient = new COSClient(cred, clientConfig);

        return cosClient;
    }



    @Bean(name = "cosTemplate")
    @Qualifier("cos")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "cos")
    public FileStorageTemplate cosTemplate(COSClient ossClient, CosProperties cosProperties) {
        return new CosTemplate(ossClient, cosProperties);
    }


    @Bean
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "minio")
    public MinioProperties minioProperties(FileStroageProperties fileStroageProperties) {
        MinioProperties minioProperties = new MinioProperties();
        minioProperties.setActive(fileStroageProperties.getActive());
        return minioProperties;
    }
    @Bean(name = "minioClient")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "minio")
    public MinioClient minioClient(MinioProperties minioProperties) {
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getAccessKeySecret())
                .build();
    }


    @Bean(name = "minioOssTemplate")
    @Qualifier("minio")
    @ConditionalOnProperty(name = "filestorage.active",havingValue = "minio")
    public FileStorageTemplate minioOssTemplate(MinioClient oss, MinioProperties properties) {
        return new MinioTemplate(oss, properties);
    }

}
