package state

import (
	"encoding/json"
	"log"
	"os"
	"sync"
	"time"
)

/* --------------------------------------------------------------------------
   CONFIG STRUCT
----------------------------------------------------------------------------*/

type Config struct {
	VMID int `json:"vmid"`

	// Container identity
	ContainerType string `json:"container_type,omitempty"`

	// Dev runtime (only for dev containers)
	Runtime string `json:"runtime,omitempty"`

	// OPTIONAL addons (role-agnostic)
	Addons []string `json:"addons,omitempty"`

	Game         string `json:"game"`
	Variant      string `json:"variant"`
	Version      string `json:"version"`
	World        string `json:"world"`
	Ports        []int  `json:"ports"`
	ArtifactPath string `json:"artifact_path"`
	JavaPath     string `json:"java_path"`
	MemoryMB     int    `json:"memory_mb"`

	// Steam + admin credentials
	SteamUser string `json:"steam_user,omitempty"`
	SteamPass string `json:"steam_pass,omitempty"`
	SteamAuth string `json:"steam_auth,omitempty"`

	AdminUser string `json:"admin_user,omitempty"`
	AdminPass string `json:"admin_pass,omitempty"`
}



/* --------------------------------------------------------------------------
   AGENT STATE ENUM
----------------------------------------------------------------------------*/

type AgentState string

const (
	StateIdle       AgentState = "idle"
	StateInstalling AgentState = "installing"
	StateStarting   AgentState = "starting"
	StateRunning    AgentState = "running"
	StateStopping   AgentState = "stopping"
	StateCrashed    AgentState = "crashed"
	StateError      AgentState = "error"
)

/* --------------------------------------------------------------------------
   GLOBAL STATE STRUCT
----------------------------------------------------------------------------*/

type agentStatus struct {
	mu          sync.Mutex
	state       AgentState
	lastChange  time.Time
	installStep string
	lastError   error
	crashCount  int
	lastCrash   time.Time
}

var global = &agentStatus{
	state:      StateIdle,
	lastChange: time.Now(),
}

/* --------------------------------------------------------------------------
   STATE GETTERS
----------------------------------------------------------------------------*/

func GetState() AgentState {
	global.mu.Lock()
	defer global.mu.Unlock()
	return global.state
}

func GetInstallStep() string {
	global.mu.Lock()
	defer global.mu.Unlock()
	return global.installStep
}

func GetError() error {
	global.mu.Lock()
	defer global.mu.Unlock()
	return global.lastError
}

func GetCrashCount() int {
	global.mu.Lock()
	defer global.mu.Unlock()
	return global.crashCount
}

func GetLastChange() time.Time {
	global.mu.Lock()
	defer global.mu.Unlock()
	return global.lastChange
}

/* --------------------------------------------------------------------------
   STATE SETTERS — unified with logging
----------------------------------------------------------------------------*/

func SetState(s AgentState) {
	global.mu.Lock()
	defer global.mu.Unlock()

	if global.state != s {
		log.Printf("[state] %s → %s\n", global.state, s)
		global.state = s
		global.lastChange = time.Now()
	}
}

func SetInstallStep(step string) {
	global.mu.Lock()
	defer global.mu.Unlock()
	global.installStep = step
}

func SetError(err error) {
	global.mu.Lock()
	defer global.mu.Unlock()
	global.lastError = err
}

func RecordCrash(err error) {
	global.mu.Lock()
	defer global.mu.Unlock()

	log.Printf("[state] crash detected: %v", err)

	global.state = StateCrashed
	global.lastError = err
	global.crashCount++
	global.lastCrash = time.Now()
}

/* --------------------------------------------------------------------------
   CONFIG SAVE / LOAD
----------------------------------------------------------------------------*/

const configPath = "/opt/zlh-agent/config/payload.json"

func SaveConfig(cfg *Config) error {
	if err := os.MkdirAll("/opt/zlh-agent/config", 0o755); err != nil {
		return err
	}

	b, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return err
	}

	return os.WriteFile(configPath, b, 0o644)
}

func LoadConfig() (*Config, error) {
	b, err := os.ReadFile(configPath)
	if err != nil {
		return nil, err
	}

	var cfg Config
	if err := json.Unmarshal(b, &cfg); err != nil {
		return nil, err
	}
	return &cfg, nil
}
