package cli

import (
	"testing"

	"github.com/spf13/cobra"
)

// findSubcommand walks cmd's subtree along path and returns the
// matching command, or nil.
func findSubcommand(root *cobra.Command, path ...string) *cobra.Command {
	cur := root
	for _, name := range path {
		var next *cobra.Command
		for _, sub := range cur.Commands() {
			if sub.Name() == name {
				next = sub
				break
			}
		}
		if next == nil {
			return nil
		}
		cur = next
	}
	return cur
}

func assertHasAlias(t *testing.T, cmd *cobra.Command, alias string) {
	t.Helper()
	if cmd == nil {
		t.Fatal("command is nil")
	}
	for _, a := range cmd.Aliases {
		if a == alias {
			return
		}
	}
	t.Errorf("%q missing alias %q; have %v", cmd.Name(), alias, cmd.Aliases)
}

func TestListCommandsHaveLsAlias(t *testing.T) {
	root := NewBangerCommand()

	cases := [][]string{
		{"vm", "list"},
		{"image", "list"},
		{"kernel", "list"},
	}
	for _, path := range cases {
		t.Run(path[len(path)-1], func(t *testing.T) {
			cmd := findSubcommand(root, path...)
			if cmd == nil {
				t.Fatalf("missing command: %v", path)
			}
			assertHasAlias(t, cmd, "ls")
		})
	}
}

func TestDeleteCommandsHaveRmAlias(t *testing.T) {
	root := NewBangerCommand()

	cases := [][]string{
		{"vm", "delete"},
		{"image", "delete"},
	}
	for _, path := range cases {
		t.Run(path[len(path)-1], func(t *testing.T) {
			cmd := findSubcommand(root, path...)
			if cmd == nil {
				t.Fatalf("missing command: %v", path)
			}
			assertHasAlias(t, cmd, "rm")
		})
	}
}

func TestVMCommandRegistersPrune(t *testing.T) {
	root := NewBangerCommand()
	cmd := findSubcommand(root, "vm", "prune")
	if cmd == nil {
		t.Fatal("vm prune not registered")
	}
	if flag := cmd.Flags().Lookup("force"); flag == nil {
		t.Error("vm prune missing --force flag")
	}
	if flag := cmd.Flags().ShorthandLookup("f"); flag == nil {
		t.Error("vm prune missing -f shorthand")
	}
}

func TestKernelRmHasDeleteAlias(t *testing.T) {
	// This already existed prior to this feature — guard against regressions.
	root := NewBangerCommand()
	cmd := findSubcommand(root, "kernel", "rm")
	if cmd == nil {
		t.Fatal("kernel rm missing")
	}
	assertHasAlias(t, cmd, "delete")
	assertHasAlias(t, cmd, "remove")
}
