package events

import (
	"context"
	"testing"

	"github.com/nexuscrm/shared/pkg/constants"
)

// TestLineageFromContext_FreshChainOnEmptyContext verifies that an empty context
// causes LineageFromContext to mint a new UUID chain ID with depth=0, isFresh=true.
func TestLineageFromContext_FreshChainOnEmptyContext(t *testing.T) {
	t.Parallel()

	chainID, chainDepth, isFresh := LineageFromContext(context.Background())

	if chainID == "" {
		t.Fatal("expected non-empty chainID for fresh chain, got empty string")
	}
	if chainDepth != 0 {
		t.Fatalf("expected chainDepth=0 for fresh chain, got %d", chainDepth)
	}
	if !isFresh {
		t.Fatal("expected isFresh=true for fresh chain, got false")
	}

	// Two calls on empty context mint two different chain IDs (no shared state).
	chainID2, _, _ := LineageFromContext(context.Background())
	if chainID == chainID2 {
		t.Fatalf("two fresh chains should have different IDs; both got %q", chainID)
	}
}

// TestLineageFromContext_InheritedChainIncrementsDepth verifies that a context
// carrying an existing chain ID returns the same ID with depth+1, isFresh=false.
// This is the parity test for Fact 2 (mint/inherit SSoT).
func TestLineageFromContext_InheritedChainIncrementsDepth(t *testing.T) {
	t.Parallel()

	parentCtx := WithLineage(context.Background(), "abc-chain-id", 2)

	chainID, chainDepth, isFresh := LineageFromContext(parentCtx)

	if chainID != "abc-chain-id" {
		t.Fatalf("expected inherited chainID=%q, got %q", "abc-chain-id", chainID)
	}
	if chainDepth != 3 {
		t.Fatalf("expected chainDepth=3 (parent=2 + 1), got %d", chainDepth)
	}
	if isFresh {
		t.Fatal("expected isFresh=false for inherited chain, got true")
	}
}

// TestWithLineage verifies the helper used by processEventAtomic restore and tests.
func TestWithLineage(t *testing.T) {
	t.Parallel()

	ctx := WithLineage(context.Background(), "chain-xyz", 5)

	idVal := ctx.Value(constants.ContextKeyAfterSaveChainID)
	if idVal == nil {
		t.Fatal("ContextKeyAfterSaveChainID not set in context after WithLineage")
	}
	if idVal.(string) != "chain-xyz" {
		t.Fatalf("expected chain-xyz, got %q", idVal)
	}

	depthVal := ctx.Value(constants.ContextKeyAfterSaveChainDepth)
	if depthVal == nil {
		t.Fatal("ContextKeyAfterSaveChainDepth not set in context after WithLineage")
	}
	if depthVal.(string) != "5" {
		t.Fatalf("expected depth string \"5\", got %q", depthVal)
	}
}
