package steme

import (
	"encoding/hex"
	"testing"
)

// TestSignerGeneration tests keypair generation and serialization.
func TestSignerGeneration(t *testing.T) {
	signer, err := GenerateSigner()
	if err != nil {
		t.Fatalf("GenerateSigner() failed: %v", err)
	}

	// Check public key is 64 hex chars (32 bytes)
	pubKey := signer.PublicKey()
	if len(pubKey) != 64 {
		t.Errorf("PublicKey() length = %d, want 64", len(pubKey))
	}

	// Check seed is 64 hex chars (32 bytes)
	seed := signer.Seed()
	if len(seed) != 64 {
		t.Errorf("Seed() length = %d, want 64", len(seed))
	}

	// Check we can reconstruct signer from seed
	signer2, err := NewSignerFromHex(seed)
	if err != nil {
		t.Fatalf("NewSignerFromHex() failed: %v", err)
	}

	if signer.PublicKey() != signer2.PublicKey() {
		t.Errorf("PublicKey mismatch after reconstruction")
	}
}

// TestSignerSignAndVerify tests signature creation and verification.
func TestSignerSignAndVerify(t *testing.T) {
	signer, err := GenerateSigner()
	if err != nil {
		t.Fatalf("GenerateSigner() failed: %v", err)
	}

	message := []byte("test message")
	signature := signer.Sign(message)

	// Signature should be 128 hex chars (64 bytes)
	if len(signature) != 128 {
		t.Errorf("Sign() signature length = %d, want 128", len(signature))
	}

	// Verify the signature
	err = Verify(signer.PublicKey(), signature, message)
	if err != nil {
		t.Errorf("Verify() failed: %v", err)
	}

	// Verify fails with wrong message
	err = Verify(signer.PublicKey(), signature, []byte("wrong message"))
	if err == nil {
		t.Errorf("Verify() should fail with wrong message")
	}
}

// TestSignerFromEnvNotSet tests that SignerFromEnv fails when var is not set.
func TestSignerFromEnvNotSet(t *testing.T) {
	_, err := SignerFromEnv("NONEXISTENT_STEME_VAR_12345")
	if err == nil {
		t.Error("SignerFromEnv() should fail when env var is not set")
	}
}

// TestNewSignerInvalidSeed tests that NewSigner fails with wrong seed size.
func TestNewSignerInvalidSeed(t *testing.T) {
	tests := []struct {
		name    string
		seedLen int
		wantErr bool
	}{
		{"empty seed", 0, true},
		{"short seed", 16, true},
		{"correct seed", 32, false},
		{"long seed", 64, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			seed := make([]byte, tt.seedLen)
			_, err := NewSigner(seed)
			if (err != nil) != tt.wantErr {
				t.Errorf("NewSigner() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

// TestVerifyInvalidInputs tests Verify with invalid inputs.
func TestVerifyInvalidInputs(t *testing.T) {
	signer, _ := GenerateSigner()
	message := []byte("test")
	validSig := signer.Sign(message)

	tests := []struct {
		name    string
		pubKey  string
		sig     string
		wantErr bool
	}{
		{"valid", signer.PublicKey(), validSig, false},
		{"invalid pubkey hex", "zzzz", validSig, true},
		{"short pubkey", "abcd", validSig, true},
		{"invalid sig hex", signer.PublicKey(), "zzzz", true},
		{"short sig", signer.PublicKey(), "abcd", true},
		{"wrong sig", signer.PublicKey(), hex.EncodeToString(make([]byte, 64)), true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := Verify(tt.pubKey, tt.sig, message)
			if (err != nil) != tt.wantErr {
				t.Errorf("Verify() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}
