package metadata

import (
	"context"
	"fmt"
	"sync"
	"testing"

	"github.com/nexuscrm/kernel/pkg/formula"
	"github.com/nexuscrm/metadata/catalogsnapshot"
)

func TestRuntimeMetadataViewContextFailsClosed(t *testing.T) {
	if view, ok := RuntimeMetadataViewFromContext(nil); ok || view != nil {
		t.Fatal("nil context resolved a Runtime metadata view")
	}
	if view, ok := RuntimeMetadataViewFromContext(WithRuntimeMetadataView(context.Background(), nil)); ok || view != nil {
		t.Fatal("nil Runtime metadata view resolved successfully")
	}
	if view, ok := RuntimeFlowWorkViewFromContext(nil); ok || view != nil {
		t.Fatal("nil context resolved a Flow work view")
	}
	if view, ok := RuntimeFlowWorkViewFromContext(WithRuntimeFlowWorkView(context.Background(), nil)); ok || view != nil {
		t.Fatal("nil Flow work view resolved successfully")
	}
}

func TestRuntimeFlowWorkViewIsAnExplicitAuxiliaryAuthority(t *testing.T) {
	primary := &catalogsnapshot.RuntimeMetadataView{}
	flow := &catalogsnapshot.RuntimeMetadataView{}
	ctx := WithRuntimeMetadataView(context.Background(), primary)
	if view, ok := RuntimeFlowWorkViewFromContext(ctx); ok || view != nil {
		t.Fatal("primary Runtime view was inferred as Flow work authority")
	}
	ctx = WithRuntimeFlowWorkView(ctx, flow)
	if view, ok := RuntimeFlowWorkViewFromContext(ctx); !ok || view != flow {
		t.Fatalf("explicit Flow work view = %#v, %v", view, ok)
	}
	if view, ok := RuntimeMetadataViewFromContext(ctx); !ok || view != primary {
		t.Fatalf("auxiliary Flow work view replaced primary view = %#v, %v", view, ok)
	}
}

func TestRuntimeFormulaEngineForViewReusesOnlyTheExactRequestBoundView(t *testing.T) {
	primary := runtimeMutationMetadataServiceView(t)
	sibling := runtimeMutationMetadataServiceView(t)
	ctx := WithRuntimeMetadataView(t.Context(), primary)

	first, bound, err := RuntimeFormulaEngineForView(ctx, sibling)
	if err != nil || !bound || first == nil {
		t.Fatalf("first sibling formula engine = %p/%v/%v", first, bound, err)
	}
	again, bound, err := RuntimeFormulaEngineForView(ctx, sibling)
	if err != nil || !bound || again != first {
		t.Fatalf("repeated sibling formula engine = %p/%v/%v, want %p", again, bound, err, first)
	}
	primaryEngine, bound, err := RuntimeFormulaEngineFromContext(ctx)
	if err != nil || !bound || primaryEngine == nil || primaryEngine == first {
		t.Fatalf("primary formula engine = %p/%v/%v, sibling %p", primaryEngine, bound, err, first)
	}

	freshRequest := WithRuntimeMetadataView(t.Context(), primary)
	freshEngine, bound, err := RuntimeFormulaEngineForView(freshRequest, sibling)
	if err != nil || !bound || freshEngine == nil || freshEngine == first {
		t.Fatalf("fresh-request formula engine = %p/%v/%v, prior %p", freshEngine, bound, err, first)
	}
	if engine, bound, err := RuntimeFormulaEngineForView(ctx, nil); err != nil || bound || engine != nil {
		t.Fatalf("nil-view formula engine = %p/%v/%v", engine, bound, err)
	}
	if engine, bound, err := RuntimeFormulaEngineForView(nil, sibling); err != nil || bound || engine != nil {
		t.Fatalf("nil-context formula engine = %p/%v/%v", engine, bound, err)
	}
}

func TestRuntimeFormulaEngineForViewConcurrentReuse(t *testing.T) {
	view := runtimeMutationMetadataServiceView(t)
	ctx := WithRuntimeMetadataView(t.Context(), view)
	const callers = 32

	engines := make(chan *formula.Engine, callers)
	errs := make(chan error, callers)
	var wg sync.WaitGroup
	for range callers {
		wg.Add(1)
		go func() {
			defer wg.Done()
			engine, bound, err := RuntimeFormulaEngineForView(ctx, view)
			if err != nil || !bound || engine == nil {
				errs <- fmt.Errorf("formula engine = %p/%v/%v", engine, bound, err)
				return
			}
			if _, err := engine.Evaluate("1 + 1 == 2", &formula.Context{}); err != nil {
				errs <- err
				return
			}
			engines <- engine
		}()
	}
	wg.Wait()
	close(errs)
	close(engines)
	for err := range errs {
		t.Fatal(err)
	}
	var first *formula.Engine
	for engine := range engines {
		if first == nil {
			first = engine
			continue
		}
		if engine != first {
			t.Fatalf("concurrent formula engine = %p, want %p", engine, first)
		}
	}
}

func BenchmarkRuntimeFormulaEngineRequestReuse(b *testing.B) {
	view := runtimeMutationMetadataServiceView(b)
	formulaContext := &formula.Context{}

	b.Run("fresh-engine", func(b *testing.B) {
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			engine, err := view.NewFormulaEngine()
			if err != nil {
				b.Fatal(err)
			}
			if _, err := engine.Evaluate("1 + 1 == 2", formulaContext); err != nil {
				b.Fatal(err)
			}
		}
	})
	b.Run("one-request-engine", func(b *testing.B) {
		ctx := WithRuntimeMetadataView(b.Context(), view)
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			engine, bound, err := RuntimeFormulaEngineForView(ctx, view)
			if err != nil || !bound {
				b.Fatalf("resolve formula engine: bound=%v err=%v", bound, err)
			}
			if _, err := engine.Evaluate("1 + 1 == 2", formulaContext); err != nil {
				b.Fatal(err)
			}
		}
	})
}
