package automation

import (
	"context"
	"testing"
	"time"

	"github.com/nexuscrm/kernel/pkg/logging"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

type recordingReplayTxStub struct {
	runTxCalls     int
	runPessTxCalls int
}

func (s *recordingReplayTxStub) WithTransaction(ctx context.Context, fn func(context.Context) error) error {
	s.runTxCalls++
	return fn(ctx)
}

func (s *recordingReplayTxStub) WithPessimisticTransaction(ctx context.Context, fn func(context.Context) error) error {
	s.runPessTxCalls++
	return fn(ctx)
}

func TestApprovalActionReplayWorkerUsesPessimisticTransaction(t *testing.T) {
	ctx := context.Background()
	store := newMemoryApprovalReplayStore(t)
	store.addPending(t, ApprovalActionReplayPayload{
		Version:             1,
		LifecycleEvent:      constants.ApprovalActionEventRecall,
		ProcessInstanceID:   "pi-pess",
		ProcessDefinitionID: "pd-pess",
		ObjectAPIName:       "GenericObject",
		TargetObjectID:      "target-pess",
		User:                &models.UserSession{ID: "005-submitter"},
		Actions: []ApprovalActionReplayFieldUpdate{{
			ActionID:           "pa-pess",
			ActionName:         "Set Recall State",
			FieldAPIName:       "LifecycleState",
			FieldValue:         "recalled",
			UpdateObjectName:   "GenericObject",
			UpdateRecordID:     "target-pess",
			UpdateFieldAPIName: "LifecycleState",
		}},
	}, time.Date(2026, 5, 15, 8, 0, 0, 0, time.UTC))

	persistence := &replayPersistenceStub{
		records: map[string]models.SObject{
			"GenericObject/target-pess": {
				"Id":             "target-pess",
				"LifecycleState": "submitted",
			},
		},
	}
	svc := NewApprovalService(persistence, nil, nil, nil, nil, nil, nil, logging.Default)
	txRunner := &recordingReplayTxStub{}
	worker := NewApprovalActionReplayWorker(store, txRunner, svc, ApprovalActionReplayConfig{
		HolderID:       "pess-worker",
		MaxAttempts:    3,
		InitialBackoff: time.Second,
		LeaseDuration:  time.Minute,
	})

	processed, err := worker.ProcessOnce(ctx)
	if err != nil {
		t.Fatalf("ProcessOnce() error = %v", err)
	}
	if processed != 1 {
		t.Fatalf("processed rows = %d, want 1", processed)
	}
	if txRunner.runPessTxCalls != 1 {
		t.Fatalf("WithPessimisticTransaction calls = %d, want 1", txRunner.runPessTxCalls)
	}
	if txRunner.runTxCalls != 0 {
		t.Fatalf("WithTransaction calls = %d, want 0", txRunner.runTxCalls)
	}
	if got := persistence.records["GenericObject/target-pess"]["LifecycleState"]; got != "recalled" {
		t.Fatalf("LifecycleState = %v, want recalled", got)
	}
}
