package backup

import (
	"fmt"
	"math/rand"
	"time"

	"github.com/tidbcloud/dataflow-service-e2e/internal/tidbcloud/dedicated/consoleapi"
	"github.com/tidbcloud/dataflow-service-e2e/internal/tidbcloud/dedicated/consoleapi/cluster_non_gen"
)

// Common test constants
const (
	// Timeout constants
	DefaultBackupTimeout  = 30 * time.Minute
	DefaultRestoreTimeout = 60 * time.Minute
	PiTRBackupTimeout     = 20 * time.Minute

	// Retry constants
	DefaultRetryAttempts = 3
	DefaultRetryInterval = time.Minute

	// Backup settings
	DefaultScheduleTime  = "03:00"
	DefaultRetentionDays = 7

	// Cluster configuration
	DefaultClusterPassword = "TestPassword123!"
	DefaultClusterPort     = 4000
)

// BuildMinimalClusterComponents returns a minimal component configuration for fast test clusters
// This provides a smaller cluster suitable for PiTR and other quick tests
func BuildMinimalClusterComponents() []*consoleapi.SimpleClusterComponentRequest {
	return []*consoleapi.SimpleClusterComponentRequest{
		{
			ComponentType:   "COMPONENT_TYPE_TIDB",
			NodeProfileName: "2C8G",
			Replicas:        1,
			StorageSizeGi:   0,
		},
		{
			ComponentType:   "COMPONENT_TYPE_TIKV",
			NodeProfileName: "2C8G",
			Replicas:        3,
			StorageSizeGi:   200,
		},
	}
}

// BuildMinimalClusterComponentsForRegion resolves the smallest available node spec for the
// target region and builds a minimal component configuration from it. This mirrors the
// cluster-creation fallback in internal/case_driver/dependency_tidb_dedicated.go (doCreateCluster)
// so restore works in regions where the default "2C8G" node profile is not available
// (previously failing with "spu not found with specified attributes"). It falls back to the
// hardcoded "2C8G" spec if the node-spec query fails or no smaller spec is found.
func BuildMinimalClusterComponentsForRegion(
	cli *cluster_non_gen.ClusterClient,
	orgID, projectID, cloudProvider, region string,
) []*consoleapi.SimpleClusterComponentRequest {
	// Default to the smallest fixed profile until we confirm a valid one for the region.
	components := BuildMinimalClusterComponents()

	regionId := fmt.Sprintf("%s-%s", cloudProvider, region)
	tidbSpec, err := cli.GetSmallestNodeSpec(orgID, projectID, regionId, "TIDB")
	if err != nil {
		return components
	}
	tikvSpec, err := cli.GetSmallestNodeSpec(orgID, projectID, regionId, "TIKV")
	if err != nil {
		return components
	}

	components[0].NodeProfileName = tidbSpec.NodeSpecKey
	components[1].NodeProfileName = tikvSpec.NodeSpecKey
	if tikvSpec.MinStorageSizeGi > 0 {
		components[1].StorageSizeGi = int(tikvSpec.MinStorageSizeGi)
	}
	return components
}

// GenerateBackupName creates a unique backup name for test purposes
func GenerateBackupName(prefix string) string {
	return fmt.Sprintf("%s-%d", prefix, time.Now().Unix())
}

// generateRandomString creates a random string of specified length using lowercase letters and numbers
func generateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[rand.Intn(len(charset))]
	}
	return string(b)
}

// GenerateClusterName creates a unique cluster name for test purposes
func GenerateClusterName(prefix string) string {
	return fmt.Sprintf("%s-%d-%s", prefix, time.Now().Unix(), generateRandomString(6))
}
