package plan

import (
	"reflect"
	"strings"
	"testing"

	"metis/pkg/config"
	"metis/pkg/secrets"
)

func TestNodeSecretHelpers(t *testing.T) {
	if got := effectiveAtlasPassword(nil); got != "" {
		t.Fatalf("effectiveAtlasPassword(nil) = %q", got)
	}
	sec := &secrets.NodeSecrets{AtlasPassword: "atlas-pass"}
	if got := effectiveAtlasPassword(sec); got != "atlas-pass" {
		t.Fatalf("effectiveAtlasPassword = %q", got)
	}
	if got := firstNonEmptyString("", " value ", "ignored"); got != "value" {
		t.Fatalf("firstNonEmptyString = %q", got)
	}
	if !hasNodePasswords(&secrets.NodeSecrets{RootPassword: "root-pass"}) {
		t.Fatal("expected root password to count as password material")
	}
	if hasNodePasswords(&secrets.NodeSecrets{}) {
		t.Fatal("empty node secrets should not count as password material")
	}
	debug := redactedSecretsForImage(&secrets.NodeSecrets{Extra: map[string]string{"b": "2", "a": "1"}})
	if !reflect.DeepEqual(debug["extra_keys"], []string{"a", "b"}) {
		t.Fatalf("redactedSecretsForImage extra_keys = %#v", debug)
	}
}

func TestNodeSecretsFromEnvAndMergeNodeSecrets(t *testing.T) {
	t.Setenv("METIS_NODE_ATLAS_PASSWORD", "atlas-pass")
	t.Setenv("METIS_NODE_ROOT_PASSWORD", "root-pass")
	envSecrets := nodeSecretsFromEnv()
	if envSecrets == nil || envSecrets.RootPassword != "root-pass" || envSecrets.AtlasPassword != "atlas-pass" {
		t.Fatalf("nodeSecretsFromEnv = %#v", envSecrets)
	}
	merged := mergeNodeSecrets(&secrets.NodeSecrets{
		AtlasPassword: "base-atlas",
		K3sToken:      "base-token",
		CloudInit:     "base-cloud",
		Extra:         map[string]string{"base": "1"},
	}, &secrets.NodeSecrets{
		AtlasPassword: "override-atlas",
		RootPassword:  "override-root",
		K3sToken:      "override-token",
		CloudInit:     "override-cloud",
		Extra:         map[string]string{"override": "2"},
	})
	if merged.K3sToken != "override-token" || merged.CloudInit != "override-cloud" || merged.AtlasPassword != "override-atlas" || merged.RootPassword != "override-root" {
		t.Fatalf("mergeNodeSecrets = %#v", merged)
	}
	if merged.Extra["base"] != "1" || merged.Extra["override"] != "2" {
		t.Fatalf("mergeNodeSecrets extras = %#v", merged.Extra)
	}
	if got := mergeNodeSecrets(nil, envSecrets); got.RootPassword != "root-pass" {
		t.Fatalf("mergeNodeSecrets nil base = %#v", got)
	}
	if got := mergeNodeSecrets(envSecrets, nil); got.AtlasPassword != "atlas-pass" {
		t.Fatalf("mergeNodeSecrets nil override = %#v", got)
	}
	t.Setenv("METIS_NODE_ATLAS_PASSWORD", "")
	t.Setenv("METIS_NODE_ROOT_PASSWORD", "")
	if got := nodeSecretsFromEnv(); got != nil {
		t.Fatalf("expected empty env secrets to collapse to nil, got %#v", got)
	}
}

func TestFirstbootEnvContentIncludesPasswords(t *testing.T) {
	cfg := &config.NodeConfig{
		Hostname: "titan-15",
		SSHUser:  "atlas",
		K3s:      config.K3sConfig{Version: "v1.31.5+k3s1"},
	}
	content := firstbootEnvContent(cfg, &secrets.NodeSecrets{
		AtlasPassword: "atlas-pass",
		RootPassword:  "root-pass",
	})
	if !reflect.DeepEqual(parseEnvLines(content), map[string]string{
		"METIS_HOSTNAME":       "'titan-15'",
		"METIS_SSH_USER":       "'atlas'",
		"METIS_ATLAS_USER":     "'atlas'",
		"METIS_K3S_VERSION":    "'v1.31.5+k3s1'",
		"METIS_ATLAS_PASSWORD": "'atlas-pass'",
		"METIS_ROOT_PASSWORD":  "'root-pass'",
	}) {
		t.Fatalf("firstbootEnvContent = %q", content)
	}
}

func parseEnvLines(raw string) map[string]string {
	result := map[string]string{}
	for _, line := range strings.Split(strings.TrimSpace(raw), "\n") {
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			continue
		}
		result[parts[0]] = parts[1]
	}
	return result
}
