package cmd

import (
	"testing"

	"git.secluded.site/keld/internal/restic"
)

func TestWrappedCommandsExist(t *testing.T) {
	t.Parallel()

	for _, wc := range wrappedCommands {
		wc := wc
		t.Run(wc.Name, func(t *testing.T) {
			t.Parallel()

			if _, ok := restic.Commands[wc.Name]; !ok {
				t.Fatalf("wrapped command %q not found in restic.Commands", wc.Name)
			}
		})
	}
}

func TestAllResticCommandsClassified(t *testing.T) {
	t.Parallel()

	wrapped := make(map[string]struct{}, len(wrappedCommands))
	for _, wc := range wrappedCommands {
		wrapped[wc.Name] = struct{}{}
	}

	for name := range restic.Commands {
		name := name
		if name == "global" {
			continue
		}

		t.Run(name, func(t *testing.T) {
			t.Parallel()

			if _, ok := wrapped[name]; ok {
				return
			}
			if _, ok := passthroughCommands[name]; ok {
				return
			}
			t.Fatalf("restic command %q is neither wrapped nor listed in passthroughCommands", name)
		})
	}
}

func TestFlagContracts(t *testing.T) {
	t.Parallel()

	for _, fc := range flagContracts {
		fc := fc
		t.Run(fc.Command+"/"+fc.Name, func(t *testing.T) {
			t.Parallel()

			cmd, ok := restic.Commands[fc.Command]
			if !ok {
				t.Fatalf("command %q not found in restic.Commands", fc.Command)
			}

			var found bool
			for _, opt := range cmd.Options {
				if opt.Name == fc.Name {
					found = true
					if opt.IsBool != fc.IsBool {
						t.Errorf("IsBool mismatch for %s/%s: got %v, want %v", fc.Command, fc.Name, opt.IsBool, fc.IsBool)
					}
					if opt.Repeatable != fc.Repeatable {
						t.Errorf("Repeatable mismatch for %s/%s: got %v, want %v", fc.Command, fc.Name, opt.Repeatable, fc.Repeatable)
					}
					break
				}
			}
			if !found {
				t.Fatalf("flag %q not found in restic command %q", fc.Name, fc.Command)
			}
		})
	}
}

// TestKeyAliasesTargetsExist verifies that the config key aliases (which are
// unexported in the config package) target flags that actually exist in
// restic's global options. The aliases are hardcoded here to mirror the
// source of truth in internal/config/config.go.
func TestKeyAliasesTargetsExist(t *testing.T) {
	t.Parallel()

	aliases := map[string]string{
		"repository": "repo",
	}

	global, ok := restic.Commands["global"]
	if !ok {
		t.Fatal("restic.Commands missing 'global' entry")
	}

	globalFlags := make(map[string]struct{}, len(global.Options))
	for _, opt := range global.Options {
		globalFlags[opt.Name] = struct{}{}
	}

	for key, target := range aliases {
		key, target := key, target
		t.Run(key+"->"+target, func(t *testing.T) {
			t.Parallel()

			if _, ok := globalFlags[target]; !ok {
				t.Fatalf("keyAlias %q -> %q: target flag %q not found in global options", key, target, target)
			}
		})
	}
}
