package plan

import (
	"fmt"
	"strings"

	"github.com/tidbcloud/observability/vm-migration/internal/schema"
)

// Stage identifiers for the prepare / migration / decommission lifecycle.
const (
	StagePrepare      = "prepare"
	StageMigration    = "migration"
	StageDecommission = "decommission"
)

// VmctlDefaultStepInterval is the default vm-native step interval stored in
// the migrate action when plan.json omits it.
const VmctlDefaultStepInterval = "day"

// ValidStepNames is the closed set of step names allowed in plan.json's
// stages — operator annotations only. Loop steps are a separate set owned by
// schema.loopStepBindings.
var ValidStepNames = []string{
	"preflight",
	"generate-tenants",
	"enable-dedup",
	"drain-insert",
	"deploy-vmselects",
	"run",
	"drain-select",
	"scale-down",
	"cleanup",
}

// Config is the validated plan.json config plus derived values.
//
// Fields include drain/retain ordinals and vmcluster YAML path.
type Config struct {
	SourceReplicaCount          int
	TargetReplicaCount          int
	DrainOrdinals               []int
	RetainOrdinals              []int
	Namespace                   string
	VmselectURLPattern          string
	VmselectMigrationURLPattern string
	VmselectCandidateURLPattern string
	VminsertURLPattern          string
	VmselectImage               string
	VmselectMigration           TargetSizing
	VmselectCandidate           TargetSizing
	Region                      string
	WindowStart                 string
	WindowEnd                   string
	ShardStepInterval           string
	VmctlRateLimit              *int
	VmctlConcurrency            *int
	VmctlStepInterval           string
	Tenants                     []string
}

// TargetSizing is one temporary vmselect's sizing, projected from the
// vmselects block of plan.json.
type TargetSizing struct {
	Replicas      *int
	CPURequest    *string
	MemoryRequest *string
	CPULimit      *string
	MemoryLimit   *string
}

// Step is one entry in steps.<stage>.items.
//
// Aliased to schema.Step so the JSON tags live next to the schema they
// describe.
type Step = schema.Step

// Stages buckets steps by stage name.
type Stages map[string][]Step

// deriveCompilePath returns <plan-dir>/<plan-stem>-compile.json.
func deriveCompilePath(planPath string) string {
	return schema.SwapSuffix(planPath, "", "-compile.json")
}

// rangeInts returns [start, end).
//
// Used to compute drain/retain vmstorage ordinal ranges from target/source
// replica counts.
func rangeInts(start, end int) []int {
	out := make([]int, 0, end-start)
	for i := start; i < end; i++ {
		out = append(out, i)
	}
	return out
}

func intsCSV(arr []int) string {
	parts := make([]string, len(arr))
	for i, n := range arr {
		parts[i] = fmt.Sprintf("%d", n)
	}
	return strings.Join(parts, ", ")
}
