package config

import (
	"context"
	"fmt"
	"log"

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

// MinioSetup struct
type MinioStorage struct {
	Cfg *Config
}

func NewMinio(cfg *Config) *MinioStorage {
	minioSetup := &MinioStorage{
		Cfg: cfg,
	}

	return minioSetup
}

func (_minio *MinioStorage) ConnectMinio() (*minio.Client, error) {
	ctx := context.Background()
	endpoint := _minio.Cfg.ObjectStorage.MinioStorage.Endpoint
	accessKeyID := _minio.Cfg.ObjectStorage.MinioStorage.AccessKeyID
	secretAccessKey := _minio.Cfg.ObjectStorage.MinioStorage.SecretAccessKey
	useSSL := _minio.Cfg.ObjectStorage.MinioStorage.UseSSL

	bucketName := _minio.Cfg.ObjectStorage.MinioStorage.BucketName
	location := _minio.Cfg.ObjectStorage.MinioStorage.Location

	// Log connection attempt
	log.Printf("[MinIO] Attempting to connect to MinIO at endpoint: %s (SSL: %v)", endpoint, useSSL)

	// Initialize minio client object.
	minioClient, errInit := minio.New(endpoint, &minio.Options{
		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
		Secure: useSSL,
	})
	if errInit != nil {
		log.Printf("[MinIO] ERROR: Failed to initialize MinIO client. Endpoint: %s, SSL: %v, Error: %v", endpoint, useSSL, errInit)
		return nil, errInit
	}

	log.Printf("[MinIO] MinIO client initialized successfully. Checking bucket: %s", bucketName)

	// Check if bucket exists first
	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
	if errBucketExists != nil {
		log.Printf("[MinIO] ERROR: Failed to check if bucket exists. Bucket: %s, Error: %v", bucketName, errBucketExists)
		return nil, errBucketExists
	}

	if exists {
		log.Printf("[MinIO] Bucket '%s' already exists and is accessible", bucketName)
	} else {
		// Try to create the bucket
		log.Printf("[MinIO] Bucket '%s' does not exist. Attempting to create it in location: %s", bucketName, location)
		err := minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{Region: location})
		if err != nil {
			log.Printf("[MinIO] ERROR: Failed to create bucket. Bucket: %s, Location: %s, Error: %v", bucketName, location, err)
			return nil, err
		}
		log.Printf("[MinIO] Successfully created bucket '%s' in location '%s'", bucketName, location)
	}

	log.Printf("[MinIO] Successfully connected to MinIO and bucket '%s' is ready", bucketName)
	return minioClient, nil
}

// PublicObjectURL builds a path-style URL for public reads (bucket policy must allow GET).
func (m *MinioStorage) PublicObjectURL(objectKey string) string {
	o := m.Cfg.ObjectStorage.MinioStorage
	scheme := "http"
	if o.UseSSL {
		scheme = "https"
	}
	return fmt.Sprintf("%s://%s/%s/%s", scheme, o.Endpoint, o.BucketName, objectKey)
}
