package config

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

	"gitea.dcglab.co.uk/steve/restic-manager/internal/crypto"
)

func TestEnsureSecretsKeyMintsOnce(t *testing.T) {
	t.Parallel()
	c := &Config{}
	if err := c.EnsureSecretsKey(); err != nil {
		t.Fatalf("mint: %v", err)
	}
	first := c.SecretsKey
	if first == "" {
		t.Fatal("EnsureSecretsKey: SecretsKey still empty")
	}
	// Second call must be a no-op (idempotent).
	if err := c.EnsureSecretsKey(); err != nil {
		t.Fatalf("second mint: %v", err)
	}
	if c.SecretsKey != first {
		t.Errorf("EnsureSecretsKey is not idempotent: %q → %q", first, c.SecretsKey)
	}

	// SecretsKeyBytes returns 32 raw bytes.
	b, err := c.SecretsKeyBytes()
	if err != nil {
		t.Fatalf("bytes: %v", err)
	}
	if len(b) != crypto.KeyLen {
		t.Errorf("decoded key len = %d, want %d", len(b), crypto.KeyLen)
	}
}

func TestSecretsKeyBytesRejectsBadInput(t *testing.T) {
	t.Parallel()
	cases := map[string]Config{
		"empty":      {SecretsKey: ""},
		"not_base64": {SecretsKey: "!!!"},
		"wrong_len":  {SecretsKey: "Zm9v"}, // "foo", 3 bytes
	}
	for name, c := range cases {
		c := c
		t.Run(name, func(t *testing.T) {
			if _, err := c.SecretsKeyBytes(); err == nil {
				t.Errorf("expected error for %s", name)
			}
		})
	}
}

func TestLoadAcceptsLegacyRepoFields(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	path := filepath.Join(dir, "agent.yaml")
	yaml := []byte(`server_url: "https://srv"
host_id: "h1"
agent_token: "tok"
repo_url: "rest:https://repo/h1"
repo_password: "secret"
`)
	if err := os.WriteFile(path, yaml, 0o600); err != nil {
		t.Fatalf("write: %v", err)
	}
	c, err := Load(path)
	if err != nil {
		t.Fatalf("load: %v", err)
	}
	if c.LegacyRepoURL != "rest:https://repo/h1" || c.LegacyRepoPassword != "secret" {
		t.Errorf("legacy fields not parsed: %+v", c)
	}
	// And on Save the legacy fields should round-trip out to the file
	// only when set (empty values use omitempty).
	c.LegacyRepoURL = ""
	c.LegacyRepoPassword = ""
	if err := c.Save(); err != nil {
		t.Fatalf("save: %v", err)
	}
	body, _ := os.ReadFile(path)
	if contains := string(body); contains == "" || stringContains(contains, "repo_password:") {
		t.Errorf("repo_password should be gone after legacy clear, got:\n%s", contains)
	}
}

func stringContains(haystack, needle string) bool {
	for i := 0; i+len(needle) <= len(haystack); i++ {
		if haystack[i:i+len(needle)] == needle {
			return true
		}
	}
	return false
}
