package provision

import "time"

// Pool is a vendor pool (doc/04 §5.2). Consumable = cheap small vendors for
// entry/free nodes; premium = stable vendors for exit / pro entry.
type Pool string

const (
	PoolConsumable Pool = "consumable"
	PoolPremium    Pool = "premium"
)

// Tier mirrors nodes.tier (free = consumable pool, pro = premium pool).
type Tier string

const (
	TierFree Tier = "free"
	TierPro  Tier = "pro"
)

// Role mirrors nodes.role.
type Role string

const (
	RoleEntry Role = "entry"
	RoleRelay Role = "relay"
	RoleExit  Role = "exit"
)

// Status mirrors the nodes.status lifecycle state machine (doc/04 §3).
type Status string

const (
	StatusProvisioning Status = "provisioning"
	StatusProbing      Status = "probing"
	StatusUp           Status = "up"
	StatusDraining     Status = "draining"
	StatusDown         Status = "down"
	StatusDestroyed    Status = "destroyed"
)

// Event mirrors the node_events.event enum.
type Event string

const (
	EventProvisioned      Event = "provisioned"
	EventProbePass        Event = "probe_pass"
	EventProbeFail        Event = "probe_fail"
	EventMarkedUp         Event = "marked_up"
	EventDraining         Event = "draining"
	EventBlockedSuspect   Event = "blocked_suspect"
	EventBlockedConfirmed Event = "blocked_confirmed"
	EventReplaced         Event = "replaced"
	EventDestroyed        Event = "destroyed"
	EventIPRotated        Event = "ip_rotated"
)

// Provider mirrors a providers row. Credentials are intentionally absent:
// they live only in independent secrets (env/file), never in this struct
// nor in the database (doc/06 §2 red line).
type Provider struct {
	ID      int64
	Name    string
	APIKind string // adapter key, e.g. "vultr", "hetzner"
	Regions []string
	Pool    Pool
	Enabled bool
}

// NodeSpec is the desired shape of a node, the input to CreateNode.
type NodeSpec struct {
	Region     string
	Role       Role
	Tier       Tier
	ProviderID int64
	// Plan is the vendor-side instance size identifier (e.g. "vc2-1c-1gb").
	Plan       string
	NameZH     string
	NameEn     string
	RealityPBK string
	RealitySNI string
	HY2Port    int
	Weight     int
	Tags       []string
}

// Node mirrors a nodes row plus the provider resource identifiers added by
// migration 000008.
type Node struct {
	ID                 int64
	UUID               string
	Region             string
	NameZH             string
	NameEn             string
	Role               Role
	Tier               Tier
	Endpoint           string // ip:port
	HY2Port            int
	RealityPBK         string
	RealitySNI         string
	ProviderID         int64
	ProviderInstanceID string
	ElasticIPID        string
	Tags               []string
	Status             Status
	Weight             int
	CreatedAt          time.Time
}

// pendingEndpoint is the placeholder written at insert time, before the vendor
// returns an IP. nodes.endpoint is NOT NULL, so we cannot leave it empty.
const pendingEndpoint = "0.0.0.0:0"

// poolForTier maps a node tier onto its vendor pool.
func poolForTier(t Tier) Pool {
	if t == TierPro {
		return PoolPremium
	}
	return PoolConsumable
}
