package upload

import (
	"context"
	"mime/multipart"
	"path"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

// AwsS3 AWS S3存储
type AwsS3 struct {
	Bucket           string
	Region           string
	Endpoint         string
	SecretID         string
	SecretKey        string
	BaseURL          string
	PathPrefix       string
	S3ForcePathStyle bool
	DisableSSL       bool
}

// NewAwsS3 创建AWS S3
func NewAwsS3(bucket, region, endpoint, secretID, secretKey, baseURL, pathPrefix string, s3ForcePathStyle, disableSSL bool) *AwsS3 {
	return &AwsS3{
		Bucket:           bucket,
		Region:           region,
		Endpoint:         endpoint,
		SecretID:         secretID,
		SecretKey:        secretKey,
		BaseURL:          baseURL,
		PathPrefix:       pathPrefix,
		S3ForcePathStyle: s3ForcePathStyle,
		DisableSSL:       disableSSL,
	}
}

func (a *AwsS3) getClient(ctx context.Context) (*s3.Client, error) {
	cfg, err := config.LoadDefaultConfig(ctx,
		config.WithRegion(a.Region),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(a.SecretID, a.SecretKey, "")),
	)
	if err != nil {
		return nil, err
	}

	client := s3.NewFromConfig(cfg, func(o *s3.Options) {
		if a.Endpoint != "" {
			o.BaseEndpoint = aws.String(a.Endpoint)
		}
		o.UsePathStyle = a.S3ForcePathStyle
	})
	return client, nil
}

// UploadFile 上传文件
func (a *AwsS3) UploadFile(file *multipart.FileHeader) (string, string, error) {
	ctx := context.Background()
	client, err := a.getClient(ctx)
	if err != nil {
		return "", "", err
	}

	// 生成文件名和路径
	fileName := GenerateFileName(file.Filename)
	filePath := GeneratePath(a.PathPrefix)
	key := path.Join(filePath, fileName)

	// 打开文件
	src, err := file.Open()
	if err != nil {
		return "", "", err
	}
	defer src.Close()

	// 上传
	contentType := file.Header.Get("Content-Type")
	_, err = client.PutObject(ctx, &s3.PutObjectInput{
		Bucket:      aws.String(a.Bucket),
		Key:         aws.String(key),
		Body:        src,
		ContentType: aws.String(contentType),
	})
	if err != nil {
		return "", "", err
	}

	// 返回访问URL和key
	accessURL := a.BaseURL + "/" + key
	return accessURL, key, nil
}

// DeleteFile 删除文件
func (a *AwsS3) DeleteFile(key string) error {
	ctx := context.Background()
	client, err := a.getClient(ctx)
	if err != nil {
		return err
	}
	_, err = client.DeleteObject(ctx, &s3.DeleteObjectInput{
		Bucket: aws.String(a.Bucket),
		Key:    aws.String(key),
	})
	return err
}
