package signing_test

import (
	"encoding/json"
	"testing"

	"github.com/forgeo/forgebucket/internal/domain/signing"
)

func TestGenerateAndSign(t *testing.T) {
	ks, err := signing.Generate()
	if err != nil {
		t.Fatalf("Generate: %v", err)
	}
	if ks.KeyID() == "" {
		t.Fatal("expected non-empty key ID")
	}
	if ks.PublicKeyPEM() == "" {
		t.Fatal("expected non-empty public key PEM")
	}
}

func TestSignAndVerify(t *testing.T) {
	ks, err := signing.Generate()
	if err != nil {
		t.Fatalf("Generate: %v", err)
	}

	content := []byte("hello, forgebucket artifact")
	bundle, err := ks.Sign(42, "binary.tar.gz", content)
	if err != nil {
		t.Fatalf("Sign: %v", err)
	}

	if bundle.MediaType != "application/vnd.forgebucket.signature.bundle+json" {
		t.Errorf("unexpected media type: %s", bundle.MediaType)
	}
	if bundle.Payload.ArtifactID != 42 {
		t.Errorf("artifact ID mismatch: got %d", bundle.Payload.ArtifactID)
	}
	if bundle.Payload.Name != "binary.tar.gz" {
		t.Errorf("name mismatch: got %s", bundle.Payload.Name)
	}
	if bundle.Payload.Digest == "" {
		t.Error("expected non-empty digest")
	}
	if bundle.Signature == "" {
		t.Error("expected non-empty signature")
	}

	bundleJSON, err := json.Marshal(bundle)
	if err != nil {
		t.Fatalf("marshal bundle: %v", err)
	}

	result, err := ks.Verify(bundleJSON)
	if err != nil {
		t.Fatalf("Verify: %v", err)
	}
	if !result.Valid {
		t.Error("expected valid=true")
	}
	if !result.KeyMatches {
		t.Error("expected keyMatchesServer=true")
	}
	if result.Digest != bundle.Payload.Digest {
		t.Errorf("digest mismatch: %s vs %s", result.Digest, bundle.Payload.Digest)
	}
}

func TestVerifyTamperedSignature(t *testing.T) {
	ks, _ := signing.Generate()
	content := []byte("artifact content")
	bundle, err := ks.Sign(1, "file.bin", content)
	if err != nil {
		t.Fatalf("Sign: %v", err)
	}

	// Tamper: valid base64 but not a valid ECDSA signature over this payload.
	// "Z2FyYmFnZQ==" decodes to "garbage" which is not a valid DER ECDSA sig.
	bundle.Signature = "Z2FyYmFnZQ=="

	bundleJSON, _ := json.Marshal(bundle)
	result, err := ks.Verify(bundleJSON)
	if err != nil {
		t.Fatalf("Verify should not error on invalid sig: %v", err)
	}
	if result.Valid {
		t.Error("expected valid=false for tampered signature")
	}
}

func TestVerifyWrongKey(t *testing.T) {
	ks1, _ := signing.Generate()
	ks2, _ := signing.Generate()

	content := []byte("artifact")
	bundle, err := ks1.Sign(10, "tool", content)
	if err != nil {
		t.Fatalf("Sign: %v", err)
	}

	bundleJSON, _ := json.Marshal(bundle)

	// Verify with ks2 — key won't match.
	result, err := ks2.Verify(bundleJSON)
	if err != nil {
		t.Fatalf("Verify: %v", err)
	}
	// Cryptographic signature is still valid (uses embedded pub key), but key doesn't match server.
	if !result.Valid {
		t.Error("signature itself should still be cryptographically valid")
	}
	if result.KeyMatches {
		t.Error("expected keyMatchesServer=false when signed by a different key")
	}
}

func TestNewFromPEM(t *testing.T) {
	ks1, err := signing.Generate()
	if err != nil {
		t.Fatalf("Generate: %v", err)
	}

	pemStr, err := ks1.PrivateKeyPEM()
	if err != nil {
		t.Fatalf("PrivateKeyPEM: %v", err)
	}

	ks2, err := signing.New(pemStr)
	if err != nil {
		t.Fatalf("New from PEM: %v", err)
	}

	if ks1.KeyID() != ks2.KeyID() {
		t.Errorf("key IDs differ: %s vs %s", ks1.KeyID(), ks2.KeyID())
	}

	// Sign with ks1, verify with ks2 (same underlying key).
	bundle, _ := ks1.Sign(5, "bin", []byte("data"))
	bundleJSON, _ := json.Marshal(bundle)

	result, err := ks2.Verify(bundleJSON)
	if err != nil {
		t.Fatalf("Verify: %v", err)
	}
	if !result.Valid {
		t.Error("expected valid=true")
	}
	if !result.KeyMatches {
		t.Error("expected keyMatchesServer=true for same key material")
	}
}
