package main

import (
	"context"
	_ "context"
	"fmt"
	"github.com/Azure/azure-storage-blob-go/azblob"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
	"log"
	"net/url"
	"strings"
	"sync/atomic"
	"time"
)

func parseAzureConnectionString(connString string) (accountName, accountKey string, err error) {
	parts := strings.Split(connString, ";")
	for _, part := range parts {
		if strings.HasPrefix(part, "AccountName=") {
			accountName = strings.TrimPrefix(part, "AccountName=")
		} else if strings.HasPrefix(part, "AccountKey=") {
			accountKey = strings.TrimPrefix(part, "AccountKey=")
		}
	}
	if accountName == "" || accountKey == "" {
		err = fmt.Errorf("无法从连接字符串中提取AccountName或AccountKey")
	}
	return
}

func main() {
	// Minio配置
	minioEndpoint := "1.1.1.1:9001"
	minioAccessKeyID := "1111"
	minioSecretAccessKey := "11111"
	minioUseSSL := false

	// Azure Blob Storage配置
	azureConnectionString := "xxxx"

	// 创建Minio客户端
	minioClient, err := minio.New(minioEndpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(minioAccessKeyID, minioSecretAccessKey, ""),
		Secure: minioUseSSL,
	})
	if err != nil {
		log.Fatalf("创建Minio客户端失败: %v", err)
	}

	// 从Azure连接字符串中提取账户名和密钥
	accountName, accountKey, err := parseAzureConnectionString(azureConnectionString)
	if err != nil {
		log.Fatalf("解析Azure连接字符串失败: %v", err)
	}

	// 创建Azure Blob Storage客户端
	azureCredential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
	if err != nil {
		log.Fatalf("创建Azure凭证失败: %v", err)
	}
	azurePipeline := azblob.NewPipeline(azureCredential, azblob.PipelineOptions{})
	azureURL, _ := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net", accountName))
	azureServiceURL := azblob.NewServiceURL(*azureURL, azurePipeline)

	// 调用上传函数  
	uploadAllFromMinioToAzure(minioClient, azureServiceURL,"minio_bucket_name", "azure_container_name")
}

// uploadAllFromMinioToAzure 函数保持不变...

func uploadAllFromMinioToAzure(minioClient *minio.Client, azureServiceURL azblob.ServiceURL, minioBucket, azureContainer string) {
	ctx := context.Background()

	// 获取Azure容器客户端
	containerURL := azureServiceURL.NewContainerURL(azureContainer)

	// 列出Minio中的所有对象
	objectCh := minioClient.ListObjects(ctx, minioBucket, minio.ListObjectsOptions{Recursive: true})

	var totalObjects int64
	var uploadedObjects int64
	var totalBytes int64
	var uploadedBytes int64

	// 计算总对象数和总字节数
	for object := range objectCh {
		if object.Err != nil {
			fmt.Printf("列出对象错误: %v\n", object.Err)
			continue
		}
		totalObjects++
		totalBytes += object.Size
	}

	// 重置objectCh
	objectCh = minioClient.ListObjects(ctx, minioBucket, minio.ListObjectsOptions{Recursive: true})

	// 创建进度显示goroutine
	done := make(chan bool)
	go func() {
		for {
			select {
			case <-done:
				return
			default:
				fmt.Printf("\rProgress: %d/%d objects, %.2f%% bytes",
					atomic.LoadInt64(&uploadedObjects),
					totalObjects,
					float64(atomic.LoadInt64(&uploadedBytes))/float64(totalBytes)*100)
				time.Sleep(time.Second)
			}
		}
	}()

	// 遍历并上传所有对象
	for object := range objectCh {
		if object.Err != nil {
			fmt.Printf("\n列出对象错误: %v\n", object.Err)
			continue
		}

		// 从Minio获取对象
		minioObject, err := minioClient.GetObject(ctx, minioBucket, object.Key, minio.GetObjectOptions{})
		if err != nil {
			fmt.Printf("\n获取对象失败 %s: %v\n", object.Key, err)
			continue
		}

		// 上传到Azure Blob
		blobURL := containerURL.NewBlockBlobURL(object.Key)
		_, err = azblob.UploadStreamToBlockBlob(ctx, minioObject, blobURL, azblob.UploadStreamToBlockBlobOptions{})
		if err != nil {
			fmt.Printf("\n上传到Azure失败 %s: %v\n", object.Key, err)
			continue
		}

		atomic.AddInt64(&uploadedObjects, 1)
		atomic.AddInt64(&uploadedBytes, object.Size)
	}

	// 停止进度显示
	done <- true

	fmt.Printf("\n上传完成。总上传对象数: %d, 总上传字节数: %d\n", uploadedObjects, uploadedBytes)
}