package cli

import (
	"os"
	"strings"
	"testing"

	"tailscale.com/ipn"
	"tailscale.com/ipn/ipnstate"
)

func TestNewRootCmdUsesMirageBrandingWhenBinaryIsMirage(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	cmd := newRootCmd()
	if got, want := cmd.Name, "mirage"; got != want {
		t.Fatalf("root command name = %q, want %q", got, want)
	}
	if got, want := cmd.ShortUsage, "mirage [flags] <subcommand> [command flags]"; got != want {
		t.Fatalf("root command usage = %q, want %q", got, want)
	}
}

func TestBrandHelpersUseMirageNames(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	if got, want := currentCLIName(), "mirage"; got != want {
		t.Fatalf("currentCLIName() = %q, want %q", got, want)
	}
	if got, want := currentProductName(), "Mirage"; got != want {
		t.Fatalf("currentProductName() = %q, want %q", got, want)
	}
	if got, want := currentDaemonName(), "miraged"; got != want {
		t.Fatalf("currentDaemonName() = %q, want %q", got, want)
	}
	if got, want := currentLocalAPIName(), "Mirage LocalAPI"; got != want {
		t.Fatalf("currentLocalAPIName() = %q, want %q", got, want)
	}
	if got, want := currentDebugCommandPrefix(), "mirage debug"; got != want {
		t.Fatalf("currentDebugCommandPrefix() = %q, want %q", got, want)
	}
	if got, want := currentNetworkLockCommandPrefix(), "mirage lock"; got != want {
		t.Fatalf("currentNetworkLockCommandPrefix() = %q, want %q", got, want)
	}
}

func TestWebCmdUsesMirageBranding(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	cmd := webCmd()
	if got, want := cmd.ShortUsage, "mirage web [flags]"; got != want {
		t.Fatalf("webCmd ShortUsage = %q, want %q", got, want)
	}
	if got, want := cmd.ShortHelp, "Run a web server for controlling Mirage"; got != want {
		t.Fatalf("webCmd ShortHelp = %q, want %q", got, want)
	}
}

func TestConfigureCmdUsesMirageBranding(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	cmd := configureCmd()
	if got, want := cmd.ShortUsage, "mirage configure <subcommand>"; got != want {
		t.Fatalf("configureCmd ShortUsage = %q, want %q", got, want)
	}
}

func TestRootCmdLongHelpUsesMirageCLIName(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	cmd := newRootCmd()
	if !strings.Contains(cmd.LongHelp, "\"mirage status --help\"") {
		t.Fatalf("root LongHelp = %q, want mirage-branded help example", cmd.LongHelp)
	}
}

func TestDebugCmdUsesMirageBranding(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	cmd := debugCmd()
	want := map[string]string{
		"daemon-logs":       "Watch miraged's server logs",
		"daemon-goroutines": "Print miraged's goroutines",
		"env":               "Print cmd/mirage environment",
	}
	for _, sub := range cmd.Subcommands {
		if wantHelp, ok := want[sub.Name]; ok && sub.ShortHelp != wantHelp {
			t.Fatalf("%s ShortHelp = %q, want %q", sub.Name, sub.ShortHelp, wantHelp)
		}
	}
}

func TestSynologyBrandHelpersUseMirageNames(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	if got, want := currentSynologyPackageName(), "Mirage"; got != want {
		t.Fatalf("currentSynologyPackageName() = %q, want %q", got, want)
	}
	if got, want := currentSynologyPackageDaemonPath(), "/var/packages/Mirage/target/bin/miraged"; got != want {
		t.Fatalf("currentSynologyPackageDaemonPath() = %q, want %q", got, want)
	}
	if got, want := currentSynologyServiceName(), "pkgctl-Mirage.service"; got != want {
		t.Fatalf("currentSynologyServiceName() = %q, want %q", got, want)
	}
}

func TestIsRunningOrStartingUsesMirageStoppedText(t *testing.T) {
	oldArgs := os.Args
	os.Args = []string{"/usr/bin/mirage"}
	t.Cleanup(func() { os.Args = oldArgs })

	got, ok := isRunningOrStarting(&ipnstate.Status{BackendState: ipn.Stopped.String()})
	if ok {
		t.Fatal("isRunningOrStarting(...Stopped) ok = true, want false")
	}
	if want := "Mirage is stopped."; got != want {
		t.Fatalf("isRunningOrStarting(...Stopped) = %q, want %q", got, want)
	}
}
