// Package byoc owns the explicit, resumable BYOC Region lifecycle. It keeps
// orchestration policy separate from the AWS, Kubernetes, and filesystem
// adapters used by the command layer.
package byoc

import (
	"context"
	"errors"
	"time"
)

const (
	JournalAPIVersion = "cp9.byoc.activation/v1alpha1"
	JournalKind       = "BYOCActivation"
)

// Stage is one resumable activation mutation boundary. All cloud-read-only
// preflight checks run before the first stage.
type Stage string

const (
	StageLease            Stage = "lease"
	StageAccountSetup     Stage = "account_setup"
	StageImageMirror      Stage = "image_mirror"
	StageControlPlaneRole Stage = "control_plane_role"
	StageNetworkAssets    Stage = "network_assets"
	StageRegionalRuntime  Stage = "regional_runtime"
	StageCatalog          Stage = "catalog"
	StageRoleChainProof   Stage = "role_chain_proof"
)

// ActivationStages is the only supported mutation order. Keep account setup
// and image mirroring ahead of regional readiness so a ready Region can never
// fall back to the control-plane registry.
var ActivationStages = []Stage{
	StageLease,
	StageAccountSetup,
	StageImageMirror,
	StageControlPlaneRole,
	StageNetworkAssets,
	StageRegionalRuntime,
	StageCatalog,
	StageRoleChainProof,
}

type ActivationState string

const (
	StateActivating ActivationState = "activating"
	StateFailed     ActivationState = "failed"
	StateReady      ActivationState = "ready"
	StateDestroyed  ActivationState = "destroyed"
)

type StageState string

const (
	StagePending StageState = "pending"
	StageRunning StageState = "running"
	StageDone    StageState = "done"
	StageFailed  StageState = "failed"
)

type AvailabilityZone struct {
	Name string `json:"name"`
	ID   string `json:"id"`
}

// Input is the complete resolved activation contract. Local profile names and
// paths are execution inputs; Fingerprint deliberately excludes them and binds
// the durable journal to the identities they resolve to during preflight.
type Input struct {
	Session               string
	Owner                 string
	Machine               string
	LeaseExpiresAt        string
	StateDir              string
	Region                string
	ControlPlaneAccountID string
	CustomerAccountID     string
	TenantID              string
	AvailabilityZones     []AvailabilityZone
	TiDBCIDR              string
	TiDBHostedZoneName    string
	TiDBHostedZoneID      string
	O11YHostedZoneName    string
	O11YHostedZoneID      string
	PCAARN                string
	ImageSyncRegion       string
	ClinicAccountID       string
	ReuseAccountSetup     bool
	ControlPlaneProfile   string
	CustomerProfile       string
	RemoteInstanceID      string
	RemotePublicIP        string
	RemoteRuntimeRoleARN  string
	RemoteSecurityGroupID string
	RemoteSubnetID        string
	KubeconfigPath        string
	KubeContext           string
	RepoRoot              string
	BundleCommit          string
	BundleDigest          string
	ImageClosureDigest    string
}

// PreflightResult records credential-free identity and prerequisite evidence.
// Drivers must not put access keys, session tokens, kubeconfigs, or profile
// contents in this value.
type PreflightResult struct {
	ControlPlaneCallerARN string            `json:"control_plane_caller_arn"`
	CustomerCallerARN     string            `json:"customer_caller_arn"`
	Observed              map[string]string `json:"observed,omitempty"`
	CompletedAt           time.Time         `json:"completed_at"`
}

type StageResult struct {
	Artifacts map[string]string
}

type ObservedStageState string

const (
	ObservedPending          ObservedStageState = "pending"
	ObservedInterrupted      ObservedStageState = "interrupted"
	ObservedFailed           ObservedStageState = "failed"
	ObservedReady            ObservedStageState = "ready"
	ObservedNeedsReconcile   ObservedStageState = "needs_reconcile"
	ObservedObservationError ObservedStageState = "observation_failed"
)

type StageObservation struct {
	State   ObservedStageState `json:"state"`
	Message string             `json:"message,omitempty"`
}

// ActivationObservation is a point-in-time, read-only view of every activation
// stage. Ready is true only when each completed stage still passes its driver's
// live revalidation.
type ActivationObservation struct {
	Ready  bool                       `json:"ready"`
	Stages map[Stage]StageObservation `json:"stages"`
}

// Driver is the system boundary for AWS, Kubernetes, registry, and remote-host
// operations. Preflight and Revalidate are strictly read-only. Apply is the
// only method permitted to mutate external state.
type Driver interface {
	Preflight(ctx context.Context, input Input, journal *Journal) (*PreflightResult, error)
	Revalidate(ctx context.Context, input Input, stage Stage, record *StageRecord) (*StageResult, error)
	Apply(ctx context.Context, input Input, stage Stage, journal *Journal) (*StageResult, error)
}

// ErrNeedsReconcile tells the engine that a previously done stage is no longer
// live and may be safely reconciled through Apply.
var ErrNeedsReconcile = errors.New("BYOC stage needs reconciliation")
