package outboxreplay

import (
	"context"
	"errors"
	"testing"
)

func TestNewScopeNormalizesAndBoundsTenantReplay(t *testing.T) {
	scope, err := NewScope(" HUWAA ", 3, 10)
	if err != nil {
		t.Fatalf("NewScope failed: %v", err)
	}
	if scope.AppCode != "huwaa" || scope.Limit != 3 {
		t.Fatalf("scope mismatch: %+v", scope)
	}
	for _, test := range []struct {
		name  string
		app   string
		limit int
		max   int
	}{
		{name: "missing app", limit: 1, max: 10},
		{name: "zero limit", app: "huwaa", max: 10},
		{name: "above maximum", app: "huwaa", limit: 11, max: 10},
		{name: "invalid maximum", app: "huwaa", limit: 1},
	} {
		t.Run(test.name, func(t *testing.T) {
			if _, err := NewScope(test.app, test.limit, test.max); err == nil {
				t.Fatal("expected validation error")
			}
		})
	}
}

func TestRunStopsAtProcessWideLimit(t *testing.T) {
	calls := 0
	result, err := Run(context.Background(), Scope{AppCode: "huwaa", Limit: 3}, func(context.Context) (int, error) {
		calls++
		return 1, nil
	})
	if err != nil {
		t.Fatalf("Run failed: %v", err)
	}
	if calls != 3 || result.Processed != 3 || result.Drained {
		t.Fatalf("hard-limit result mismatch: calls=%d result=%+v", calls, result)
	}
}

func TestRunStopsWhenPartitionDrains(t *testing.T) {
	calls := 0
	result, err := Run(context.Background(), Scope{AppCode: "huwaa", Limit: 5}, func(context.Context) (int, error) {
		calls++
		if calls == 3 {
			return 0, nil
		}
		return 1, nil
	})
	if err != nil {
		t.Fatalf("Run failed: %v", err)
	}
	if calls != 3 || result.Processed != 2 || !result.Drained {
		t.Fatalf("drained result mismatch: calls=%d result=%+v", calls, result)
	}
}

func TestRunCountsClaimedFailureAndRejectsBatchClaims(t *testing.T) {
	publishErr := errors.New("publish failed")
	result, err := Run(context.Background(), Scope{AppCode: "huwaa", Limit: 5}, func(context.Context) (int, error) {
		return 1, publishErr
	})
	if !errors.Is(err, publishErr) || result.Processed != 1 {
		t.Fatalf("failed row result mismatch: result=%+v err=%v", result, err)
	}

	if _, err := Run(context.Background(), Scope{AppCode: "huwaa", Limit: 5}, func(context.Context) (int, error) {
		return 2, nil
	}); err == nil {
		t.Fatal("expected multi-row claim rejection")
	}
}
