package storage

import (
	"fmt"
	"strings"

	"github.com/pingcap/log"
	"github.com/tidbcloud/observability/vmbackupmanager/pkg/config"
	"go.uber.org/zap"
)

// NewStorage creates a storage implementation based on the provided URI
// dst is the storage path, e.g. s3://bucket/path, gs://bucket/path, azblob://container/path, fs:///local/path
func NewStorage(cfg *config.Config) (Interface, error) {
	storageInfo := ParseStoragePath(cfg.Destination)

	log.Info("Creating storage client", zap.String("type", string(storageInfo.Type)), zap.String("fullPath", storageInfo.FullPath))

	switch storageInfo.Type {
	case StorageTypeS3, StorageTypeGCS, StorageTypeAzure:
		return NewS3Storage(cfg)
	case StorageTypeFS:
		return NewFSStorage(cfg.Destination), nil
	default:
		return nil, fmt.Errorf("unsupported storage type: %s", storageInfo.Type)
	}
}

// StorageInfo contains information about a storage location
type StorageInfo struct {
	// Type is the storage provider type (s3, gs, azblob, fs)
	Type StorageType
	// Bucket is the bucket/container name
	Bucket string
	// Prefix is the path prefix within the bucket
	Prefix string
	// FullPath is the original full path with "/" suffix.
	FullPath string
}

// ParseStoragePath parses a storage path and returns information about the storage location
// Supports formats: s3://bucket/path, gs://bucket/path, azblob://container/path, fs:///local/path
func ParseStoragePath(path string) StorageInfo {
	result := StorageInfo{
		FullPath: path,
	}

	// Handle local filesystem paths
	if strings.HasPrefix(path, "fs://") {
		result.Type = StorageTypeFS
		result.Prefix = strings.TrimPrefix(path, "fs://")
		return result
	}

	// Handle cloud storage paths
	parts := strings.SplitN(path, "://", 2)
	if len(parts) != 2 {
		// Invalid format, return empty info
		return result
	}

	// Set the storage type
	switch parts[0] {
	case "s3":
		result.Type = StorageTypeS3
	case "gs":
		result.Type = StorageTypeGCS
	case "azblob":
		result.Type = StorageTypeAzure
	default:
		// Unknown storage type
		return result
	}

	// Parse bucket and prefix
	pathParts := strings.SplitN(parts[1], "/", 2)
	result.Bucket = pathParts[0]

	if len(pathParts) > 1 {
		result.Prefix = pathParts[1]
		// Add trailing slash if needed
		if result.Prefix != "" && !strings.HasSuffix(result.Prefix, "/") {
			result.Prefix += "/"
			result.FullPath += "/"
		}
	} else {
		result.Prefix = ""
	}

	return result
}
