package webauthn

import (
	"path/filepath"
	"testing"
	"time"
)

// TestStoreRoundTrip verifies Put + Get + Delete + List + UpdateSignCount.
func TestStoreRoundTrip(t *testing.T) {
	dbPath := filepath.Join(t.TempDir(), "webauthn-creds.db")
	store, err := NewStore(dbPath)
	if err != nil {
		t.Fatalf("NewStore: %v", err)
	}
	defer store.Close()

	cred := &Credential{
		UserID:       "user-1",
		CredentialID: []byte("cred-id-123"),
		PublicKey:    []byte("pub-key-bytes"),
		SignCount:    0,
		AAGUID:       "test-aaguid",
		CreatedAt:    time.Now(),
	}
	if err := store.PutCredential(cred); err != nil {
		t.Fatalf("Put: %v", err)
	}
	got, err := store.GetCredential("user-1")
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if got == nil {
		t.Fatal("Get returned nil")
	}
	if got.UserID != "user-1" || string(got.CredentialID) != "cred-id-123" {
		t.Errorf("got = %+v", got)
	}
	if err := store.UpdateSignCount("user-1", 42); err != nil {
		t.Fatalf("UpdateSignCount: %v", err)
	}
	got, _ = store.GetCredential("user-1")
	if got.SignCount != 42 {
		t.Errorf("SignCount = %d, want 42", got.SignCount)
	}
	list, err := store.ListCredentials()
	if err != nil {
		t.Fatalf("List: %v", err)
	}
	if len(list) != 1 {
		t.Errorf("List = %d, want 1", len(list))
	}
	if err := store.DeleteCredential("user-1"); err != nil {
		t.Fatalf("Delete: %v", err)
	}
	got, _ = store.GetCredential("user-1")
	if got != nil {
		t.Error("Get after delete should return nil")
	}
}

// TestStorePutReplace verifies Put replaces on conflict.
func TestStorePutReplace(t *testing.T) {
	dbPath := filepath.Join(t.TempDir(), "webauthn-creds.db")
	store, _ := NewStore(dbPath)
	defer store.Close()
	c1 := &Credential{UserID: "u", CredentialID: []byte("old"), PublicKey: []byte("pk1"), CreatedAt: time.Now()}
	store.PutCredential(c1)
	c2 := &Credential{UserID: "u", CredentialID: []byte("new"), PublicKey: []byte("pk2"), CreatedAt: time.Now()}
	store.PutCredential(c2)
	got, _ := store.GetCredential("u")
	if string(got.CredentialID) != "new" {
		t.Errorf("CredentialID = %q, want new", got.CredentialID)
	}
}

// TestStoreGetMissing verifies Get returns nil, nil for missing.
func TestStoreGetMissing(t *testing.T) {
	dbPath := filepath.Join(t.TempDir(), "webauthn-creds.db")
	store, _ := NewStore(dbPath)
	defer store.Close()
	got, err := store.GetCredential("nonexistent")
	if err != nil {
		t.Errorf("Get missing should not error: %v", err)
	}
	if got != nil {
		t.Error("Get missing should return nil")
	}
}

// TestEncodeDecodeID verifies base64 round-trip.
func TestEncodeDecodeID(t *testing.T) {
	original := []byte("test-credential-id-12345")
	encoded := EncodeID(original)
	decoded, err := DecodeID(encoded)
	if err != nil {
		t.Fatalf("Decode: %v", err)
	}
	if string(decoded) != string(original) {
		t.Errorf("decode = %q, want %q", decoded, original)
	}
}
