package vault

import (
	"strings"
	"testing"
)

func TestDeriveKeyConsistent(t *testing.T) {
	salt := []byte("test-salt-exactly-32-bytes-long!")
	key1 := DeriveKey("mypassword", salt)
	key2 := DeriveKey("mypassword", salt)

	if len(key1) != 32 {
		t.Errorf("key length = %d, want 32", len(key1))
	}
	if string(key1) != string(key2) {
		t.Error("same password+salt produced different keys")
	}
}

func TestDeriveKeyDifferentPasswords(t *testing.T) {
	salt := []byte("test-salt-exactly-32-bytes-long!")
	key1 := DeriveKey("password1", salt)
	key2 := DeriveKey("password2", salt)

	if string(key1) == string(key2) {
		t.Error("different passwords produced same key")
	}
}

func TestEncryptDecryptRoundTrip(t *testing.T) {
	key := DeriveKey("testpassword", []byte("test-salt-exactly-32-bytes-long!"))
	vs := NewVaultService(key)

	plaintext := "super-secret-ssh-key-data"
	encrypted, err := vs.Encrypt(plaintext)
	if err != nil {
		t.Fatalf("Encrypt() error: %v", err)
	}

	if !strings.HasPrefix(encrypted, "v1:") {
		t.Errorf("encrypted does not start with v1: prefix: %q", encrypted[:10])
	}

	decrypted, err := vs.Decrypt(encrypted)
	if err != nil {
		t.Fatalf("Decrypt() error: %v", err)
	}

	if decrypted != plaintext {
		t.Errorf("Decrypt() = %q, want %q", decrypted, plaintext)
	}
}

func TestEncryptProducesDifferentCiphertexts(t *testing.T) {
	key := DeriveKey("testpassword", []byte("test-salt-exactly-32-bytes-long!"))
	vs := NewVaultService(key)

	enc1, _ := vs.Encrypt("same-data")
	enc2, _ := vs.Encrypt("same-data")

	if enc1 == enc2 {
		t.Error("two encryptions of same data produced identical ciphertext (IV reuse)")
	}
}

func TestDecryptWrongKey(t *testing.T) {
	key1 := DeriveKey("password1", []byte("test-salt-exactly-32-bytes-long!"))
	key2 := DeriveKey("password2", []byte("test-salt-exactly-32-bytes-long!"))

	vs1 := NewVaultService(key1)
	vs2 := NewVaultService(key2)

	encrypted, _ := vs1.Encrypt("secret")
	_, err := vs2.Decrypt(encrypted)
	if err == nil {
		t.Error("Decrypt() with wrong key should return error")
	}
}

func TestDecryptInvalidFormat(t *testing.T) {
	key := DeriveKey("test", []byte("test-salt-exactly-32-bytes-long!"))
	vs := NewVaultService(key)

	_, err := vs.Decrypt("not-valid-format")
	if err == nil {
		t.Error("Decrypt() with invalid format should return error")
	}
}

func TestGenerateSalt(t *testing.T) {
	salt1, err := GenerateSalt()
	if err != nil {
		t.Fatalf("GenerateSalt() error: %v", err)
	}
	if len(salt1) != 32 {
		t.Errorf("salt length = %d, want 32", len(salt1))
	}

	salt2, _ := GenerateSalt()
	if string(salt1) == string(salt2) {
		t.Error("two calls to GenerateSalt produced identical salt")
	}
}
