package validjson

import (
	"context"
	"testing"

	"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
)

func TestValidatorAcceptsValidJSON(t *testing.T) {
	tests := []string{
		`{"value":true}`,
		`[1,2,3]`,
		`"value"`,
	}
	for _, payload := range tests {
		result, err := New(Options{}).Validate(context.Background(), requestWithPayload(payload))
		if err != nil {
			t.Fatalf("Validate(%s) error = %v, want nil", payload, err)
		}
		if !result.Approved {
			t.Fatalf("Validate(%s) = %#v, want approved", payload, result)
		}
	}
}

func TestValidatorRejectsInvalidJSON(t *testing.T) {
	result, err := New(Options{}).Validate(context.Background(), requestWithPayload(`{"value":`))
	if err != nil {
		t.Fatalf("Validate() error = %v, want nil", err)
	}
	if result.Approved {
		t.Fatalf("Approved = true, want false")
	}
	if result.ReasonCode != ReasonCodeInvalidJSON {
		t.Fatalf("ReasonCode = %q, want %q", result.ReasonCode, ReasonCodeInvalidJSON)
	}
}

func TestSpecAndRegister(t *testing.T) {
	if Spec().Key != Key || Spec().ExecutionClass != contracts.ExecutionClassDeterministic {
		t.Fatalf("Spec() = %#v, want key and deterministic execution", Spec())
	}

	registry := pipeline.NewValidatorRegistry()
	if err := Register(registry); err != nil {
		t.Fatalf("Register() error = %v, want nil", err)
	}
	if registered, ok := registry.Spec(Key); !ok || registered.Key != Key {
		t.Fatalf("Spec(%q) = %#v, %v", Key, registered, ok)
	}
}

func requestWithPayload(payload string) contracts.SerializedValidationRequest {
	return contracts.SerializedValidationRequest{Content: []byte(payload), MediaType: "application/json"}
}
