package auth

import (
	"strings"
	"testing"
)

func TestHashAndVerify(t *testing.T) {
	t.Parallel()

	pw := "correct horse battery staple"
	h, err := HashPassword(pw)
	if err != nil {
		t.Fatalf("hash: %v", err)
	}
	if !strings.HasPrefix(h, "$argon2id$") {
		t.Errorf("encoded form should start $argon2id$, got %q", h)
	}
	if err := VerifyPassword(h, pw); err != nil {
		t.Errorf("verify: %v", err)
	}
	if err := VerifyPassword(h, "wrong"); err == nil {
		t.Error("verify with wrong password should fail")
	}
}

func TestEachHashIsUnique(t *testing.T) {
	t.Parallel()
	// Same password hashed twice → different encoded strings (different
	// salts). If this fails the salt is deterministic.
	a, _ := HashPassword("hunter2")
	b, _ := HashPassword("hunter2")
	if a == b {
		t.Fatal("two hashes of the same password collided — non-random salt?")
	}
}

func TestVerifyRejectsMalformed(t *testing.T) {
	t.Parallel()
	cases := []string{
		"",
		"not-a-hash",
		"$argon2i$v=19$m=64,t=3,p=4$AAAA$BBBB",  // wrong variant
		"$argon2id$",                            // truncated
		"$argon2id$v=99$m=64,t=3,p=4$AAAA$BBBB", // bad version
	}
	for _, c := range cases {
		if err := VerifyPassword(c, "anything"); err == nil {
			t.Errorf("should reject malformed hash %q", c)
		}
	}
}

func TestNewTokenUnique(t *testing.T) {
	t.Parallel()
	a, err := NewToken()
	if err != nil {
		t.Fatalf("token: %v", err)
	}
	b, _ := NewToken()
	if a == b {
		t.Fatal("two tokens collided — broken randomness")
	}
	if len(a) < 40 {
		t.Errorf("token suspiciously short: %q (%d bytes)", a, len(a))
	}
}

func TestHashTokenStable(t *testing.T) {
	t.Parallel()
	// Same input → same hash. This is not a security property, just a
	// sanity check that we're using a regular hash not a salted one.
	h1 := HashToken("foo")
	h2 := HashToken("foo")
	if h1 != h2 {
		t.Errorf("HashToken not deterministic: %q vs %q", h1, h2)
	}
	if len(h1) != 64 { // sha256 hex
		t.Errorf("expected 64-char hex hash, got %d", len(h1))
	}
}
