// MinIO 对象存储客户端封装
package minio

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"path/filepath"
	"time"

	myconfig "com.sclktx/m/v2/internal/pkg/config"

	"github.com/google/uuid"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

// Client MinIO 客户端
type Client struct {
	client *minio.Client
	config *myconfig.MinIOConfig
}

// NewClient 创建 MinIO 客户端
func NewClient(cfg *myconfig.MinIOConfig) (*Client, error) {
	minioClient, err := minio.New(cfg.Endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(cfg.AccessKey, cfg.SecretKey, ""),
		Secure: cfg.UseSSL,
	})
	if err != nil {
		return nil, fmt.Errorf("创建 MinIO 客户端失败：%w", err)
	}

	// 确保 bucket 存在
	ctx := context.Background()
	exists, err := minioClient.BucketExists(ctx, cfg.Bucket)
	if err != nil {
		return nil, fmt.Errorf("检查 bucket 失败：%w", err)
	}

	if !exists {
		// 创建 bucket
		err = minioClient.MakeBucket(ctx, cfg.Bucket, minio.MakeBucketOptions{})
		if err != nil {
			return nil, fmt.Errorf("创建 bucket 失败：%w", err)
		}
	}

	return &Client{
		client: minioClient,
		config: cfg,
	}, nil
}

// UploadFile 上传文件到 MinIO
// 返回文件的公开访问 URL
func (c *Client) UploadFile(ctx context.Context, reader io.Reader, objectName string, contentType string) (string, error) {
	// 上传文件
	info, err := c.client.PutObject(ctx, c.config.Bucket, objectName, reader, -1, minio.PutObjectOptions{
		ContentType: contentType,
	})
	if err != nil {
		return "", fmt.Errorf("上传文件失败：%w", err)
	}

	// 生成公开访问 URL（不带签名，永久有效）
	// 如果配置了 base_url（可带协议如 https://），直接使用
	// 否则用 endpoint（需自行保证协议正确）
	urlBase := c.config.BaseURL
	if urlBase == "" {
		urlBase = c.config.Endpoint
	}
	url := fmt.Sprintf("%s/%s/%s", urlBase, c.config.Bucket, info.Key)
	return url, nil
}

// UploadImage 上传图片文件
// 自动生成唯一的文件名（UUID + 时间戳 + 扩展名）
func (c *Client) UploadImage(ctx context.Context, data []byte, filename string) (string, error) {
	// 生成唯一的文件名
	ext := filepath.Ext(filename)
	if ext == "" {
		ext = ".jpg" // 默认扩展名
	}

	// 使用 UUID + 时间戳生成唯一文件名
	objectName := fmt.Sprintf("images/%s_%s%s",
		time.Now().Format("20060102150405"),
		uuid.New().String()[:8],
		ext,
	)

	// 判断内容类型
	contentType := "image/jpeg"
	switch ext {
	case ".png":
		contentType = "image/png"
	case ".gif":
		contentType = "image/gif"
	case ".webp":
		contentType = "image/webp"
	case ".jpg", ".jpeg":
		contentType = "image/jpeg"
	}

	// 上传
	reader := bytes.NewReader(data)
	return c.UploadFile(ctx, reader, objectName, contentType)
}

// GetClient 获取原始 MinIO 客户端
func (c *Client) GetClient() *minio.Client {
	return c.client
}

// GetConfig 获取配置
func (c *Client) GetConfig() *myconfig.MinIOConfig {
	return c.config
}
