package service

import (
	"bytes"
	"encoding/base64"
	"testing"
)

func TestNewAESGCMProtectorFromBase64(t *testing.T) {
	if _, err := NewAESGCMProtectorFromBase64(""); err == nil {
		t.Fatalf("expected error for empty key")
	}
	if _, err := NewAESGCMProtectorFromBase64("not-base64"); err == nil {
		t.Fatalf("expected error for invalid base64")
	}
	shortKey := make([]byte, 16)
	if _, err := NewAESGCMProtectorFromBase64(base64.StdEncoding.EncodeToString(shortKey)); err == nil {
		t.Fatalf("expected error for non-32-byte key")
	}
}

func TestAESGCMProtector_EncryptDecrypt_RoundTrip(t *testing.T) {
	key := make([]byte, 32)
	for i := range key {
		key[i] = byte(i + 1)
	}
	p, err := NewAESGCMProtectorFromBase64(base64.StdEncoding.EncodeToString(key))
	if err != nil {
		t.Fatalf("new protector: %v", err)
	}

	plain := []byte("hello-secret")
	ciphertext, err := p.Encrypt(plain)
	if err != nil {
		t.Fatalf("encrypt: %v", err)
	}
	if bytes.Equal(ciphertext, plain) {
		t.Fatalf("ciphertext should differ from plain")
	}

	decrypted, err := p.Decrypt(ciphertext)
	if err != nil {
		t.Fatalf("decrypt: %v", err)
	}
	if !bytes.Equal(decrypted, plain) {
		t.Fatalf("decrypted plaintext mismatch")
	}
}

func TestAESGCMProtector_Decrypt_CiphertextTooShort(t *testing.T) {
	key := make([]byte, 32)
	for i := range key {
		key[i] = byte(i + 1)
	}
	p, err := NewAESGCMProtectorFromBase64(base64.StdEncoding.EncodeToString(key))
	if err != nil {
		t.Fatalf("new protector: %v", err)
	}

	if _, err := p.Decrypt([]byte("short")); err == nil {
		t.Fatalf("expected ciphertext too short error")
	}
}

func TestAESGCMProtector_Decrypt_TamperedCiphertext(t *testing.T) {
	key := make([]byte, 32)
	for i := range key {
		key[i] = byte(i + 1)
	}
	p, err := NewAESGCMProtectorFromBase64(base64.StdEncoding.EncodeToString(key))
	if err != nil {
		t.Fatalf("new protector: %v", err)
	}

	ciphertext, err := p.Encrypt([]byte("hello-secret"))
	if err != nil {
		t.Fatalf("encrypt: %v", err)
	}
	ciphertext[len(ciphertext)-1] ^= 0x01

	if _, err := p.Decrypt(ciphertext); err == nil {
		t.Fatalf("expected auth failure for tampered ciphertext")
	}
}

func TestAESGCMProtector_EncryptDecrypt_InvalidKey(t *testing.T) {
	p := &AESGCMProtector{key: []byte("short")}
	if _, err := p.Encrypt([]byte("hello")); err == nil {
		t.Fatalf("expected encrypt error for invalid key")
	}
	if _, err := p.Decrypt([]byte("cipher")); err == nil {
		t.Fatalf("expected decrypt error for invalid key")
	}
}
