package packs

import (
	"errors"
	"fmt"
	"testing"
)

func TestIsDeterministicProjectionDriftRequiresEveryTypedLeaf(t *testing.T) {
	drift := &ProjectionDriftError{Expected: []byte(`{"value":1}`), Live: []byte(`{"value":2}`)}
	if !IsDeterministicProjectionDrift(drift) {
		t.Fatal("typed projection drift was not classified as deterministic")
	}

	aggregate := &ComponentVerifyErrors{errs: []*ComponentVerifyError{
		{Kind: ComponentKind("first"), BusinessKey: "one", Err: drift},
		{Kind: ComponentKind("second"), BusinessKey: "two", Err: fmt.Errorf("wrapped: %w", drift)},
	}}
	if !IsDeterministicProjectionDrift(aggregate) {
		t.Fatal("all-drift aggregate was not classified as deterministic")
	}

	mixed := &ComponentVerifyErrors{errs: []*ComponentVerifyError{
		{Kind: ComponentKind("first"), BusinessKey: "one", Err: drift},
		{Kind: ComponentKind("second"), BusinessKey: "two", Err: errors.New("database unavailable")},
	}}
	if IsDeterministicProjectionDrift(mixed) {
		t.Fatal("mixed drift and database failure must remain fail closed")
	}
	if IsDeterministicProjectionDrift(errors.Join(drift, errors.New("database unavailable"))) {
		t.Fatal("joined drift and database failure must remain fail closed")
	}
	if IsDeterministicProjectionDrift(errors.Join(aggregate, errors.New("transport unavailable"))) {
		t.Fatal("aggregate drift with a sibling transport failure must remain fail closed")
	}
	if IsDeterministicProjectionDrift(errors.New("projection drift: expected x, live y")) {
		t.Fatal("error text must not authorize deterministic repair")
	}
	if IsDeterministicProjectionDrift(nil) {
		t.Fatal("nil error must not be classified as drift")
	}
}
