package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	alibabaEndpoint := "oss-eu-central-1.aliyuncs.com"
	alibabaKey := "LTAI5tCxbGnEBAj9RS5JpLWw"
	alibabaSecret := "qAS8Rsi3MpRrV043fgxnW6fmUsQ8GN"
	bucketName := "vcard-usite"

	minioEndpoint := "135.181.2.237:9000"
	minioKey := "admin"
	minioSecret := "lsE6TAihW98iaXKDWG+6gGLYAFdyp2iC"

	log.Println("Conectando a Alibaba OSS...")
	alibabaClient, err := oss.New(alibabaEndpoint, alibabaKey, alibabaSecret)
	if err != nil {
		log.Fatalf("Error conectando a Alibaba: %v", err)
	}
	alibabaBucket, err := alibabaClient.Bucket(bucketName)
	if err != nil {
		log.Fatalf("Error obteniendo bucket Alibaba: %v", err)
	}

	log.Println("Conectando a MinIO S3...")
	minioClient, err := minio.New(minioEndpoint, &minio.Options{
		Creds:        credentials.NewStaticV4(minioKey, minioSecret, ""),
		Secure:       false,
		BucketLookup: minio.BucketLookupPath,
	})
	if err != nil {
		log.Fatalf("Error conectando a MinIO: %v", err)
	}

	ctx := context.Background()

	// Asegurar que el bucket existe en MinIO
	exists, err := minioClient.BucketExists(ctx, bucketName)
	if err != nil {
		log.Fatalf("Error verificando bucket MinIO: %v", err)
	}
	if !exists {
		err = minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{Region: "us-east-1"})
		if err != nil {
			log.Fatalf("Error creando bucket MinIO: %v", err)
		}
		log.Printf("Bucket '%s' creado en MinIO", bucketName)
	}

	log.Println("Listando objetos de Alibaba OSS...")
	var totalObjects, skipped int64
	marker := oss.Marker("vcf/vcf-Guido_Maffet-nxh4.vcf")
	for {
		resp, err := alibabaBucket.ListObjects(oss.MaxKeys(1000), marker)
		if err != nil {
			log.Fatalf("Error listando objetos Alibaba: %v", err)
		}

		for _, obj := range resp.Objects {
			totalObjects++
			// Saltar si ya existe en MinIO (mismo tamaño)
			info, err := minioClient.StatObject(ctx, bucketName, obj.Key, minio.StatObjectOptions{})
			if err == nil && info.Size == obj.Size {
				skipped++
				continue
			}

			fmt.Printf("[%d] Migrando: %s (%s)...\n", totalObjects, obj.Key, formatSize(obj.Size))

			reader, err := alibabaBucket.GetObject(obj.Key)
			if err != nil {
				log.Printf("  ERROR leyendo de Alibaba: %v", err)
				continue
			}

			_, err = minioClient.PutObject(ctx, bucketName, obj.Key, reader, obj.Size, minio.PutObjectOptions{})
			reader.Close()
			if err != nil {
				log.Printf("  ERROR subiendo a MinIO: %v", err)
				continue
			}

			fmt.Printf("  ✓ OK\n")
			time.Sleep(10 * time.Millisecond)
		}

		if !resp.IsTruncated {
			break
		}
		marker = oss.Marker(resp.NextMarker)
	}

	log.Printf("Migración completada. %d objetos totales, %d saltados (ya existen), %d migrados.", totalObjects, skipped, totalObjects-skipped)
}

func formatSize(bytes int64) string {
	if bytes < 1024 {
		return fmt.Sprintf("%d B", bytes)
	} else if bytes < 1024*1024 {
		return fmt.Sprintf("%.1f KB", float64(bytes)/1024)
	} else if bytes < 1024*1024*1024 {
		return fmt.Sprintf("%.1f MB", float64(bytes)/(1024*1024))
	}
	return fmt.Sprintf("%.1f GB", float64(bytes)/(1024*1024*1024))
}
