package connector_inbound

import (
	"context"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	connector_workqueue "github.com/pingcap-inc/nexuscrm-connectors/features/connector/workqueue"
	contractmodels "github.com/pingcap-inc/nexuscrm-contract/pkg/models"
)

func boundIdentityDependencyForTest(t *testing.T, recordID, remoteID string) contractmodels.FlowExecutionDependency {
	t.Helper()
	request, err := contractmodels.NewFlowIdentityConvergenceDependencyRequest(
		"Lead",
		recordID,
		"pingcap-hubspot-companion",
		"hubspot-contact",
	)
	if err != nil {
		t.Fatalf("NewFlowIdentityConvergenceDependencyRequest: %v", err)
	}
	dependency, err := contractmodels.BindFlowIdentityConvergenceDependency(request, "hubspot", "contacts", remoteID)
	if err != nil {
		t.Fatalf("BindFlowIdentityConvergenceDependency: %v", err)
	}
	return dependency
}

func TestWorkItemDependencyBlockPersistsImmediateRaceClosureWithoutFailureBudget(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	dependency := boundIdentityDependencyForTest(t, "00Q000000000002AAA", "contact-1")
	mock.ExpectExec(`(?s)UPDATE _System_ConnectorWorkItem.*State = \?.*DependencyKind = \?.*DependencyObjectAPIName = \?.*DependencyRecordId = \?.*DependencyKeyHash = \?.*DependencyConnectorOwnerKey = \?.*DependencyConnectorNamespace = \?.*DependencyConnectorSourceObject = \?.*DependencyDestinationSlotId = \?.*DependencyConnectorRemoteId = \?.*DependencyBlockedAt = \?.*DependencyProbeAfter = \?.*LeaseOwner = NULL.*WHERE WorkId = \?.*EventId = \?.*State = \?.*LeaseToken = \?`).
		WithArgs(
			connector_workqueue.WorkStateDependencyBlocked,
			dependency.Kind, dependency.ObjectAPIName, dependency.RecordID, dependency.KeyHash,
			dependency.ConnectorOwnerKey, dependency.ConnectorNamespace, dependency.ConnectorSourceObject,
			dependency.DestinationSlotID, dependency.ConnectorRemoteID,
			sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(),
			"work-1", "event-1", connector_workqueue.WorkStateProcessing, "lease-1",
		).
		WillReturnResult(sqlmock.NewResult(0, 1))
	service := &workItemEventsService{
		claims: connector_workqueue.NewRepository(db, nil, nil),
		claimed: map[string]claimedWorkItemRef{
			"event-1": {workID: "work-1", leaseToken: "lease-1"},
		},
		peeked: make(map[string]string),
	}
	probe := IdentityConvergenceProbe{
		Namespace: "hubspot", ObjectKind: "contacts", SourceID: "contact-1", Dependency: dependency,
	}
	if err := service.BlockOnIdentityConvergence(context.Background(), "event-1", "lease-1", probe); err != nil {
		t.Fatalf("BlockOnIdentityConvergence: %v", err)
	}
	if _, ok := service.claimed["event-1"]; ok {
		t.Fatal("claimed lease retained after durable dependency block")
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sqlmock expectations: %v", err)
	}
}
