package connector_outboundintent

import (
	"errors"
	"regexp"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	connector_callout "github.com/pingcap-inc/nexuscrm-connectors/features/connector/callout"
	catalogv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
)

func TestRequireExactActivePackGenerationBindsProfilePayloadDigest(t *testing.T) {
	for _, test := range []struct {
		name    string
		rows    *sqlmock.Rows
		wantErr bool
	}{
		{name: "exact active generation", rows: sqlmock.NewRows([]string{"present"}).AddRow(1)},
		{name: "missing exact generation", rows: sqlmock.NewRows([]string{"present"}), wantErr: true},
	} {
		t.Run(test.name, func(t *testing.T) {
			db, mock, err := sqlmock.New()
			if err != nil {
				t.Fatal(err)
			}
			defer db.Close()
			mock.ExpectQuery(regexp.QuoteMeta(`SELECT 1
  FROM _System_PackGeneration
 WHERE PackName = ? AND PackInstallId = ? AND Status = 'active'
   AND AppliedPayloadHash = ? AND DesiredPayloadHash = AppliedPayloadHash
   AND COALESCE(IsDeleted, 0) = 0
 LIMIT 1`)).
				WithArgs("profile-owner", "profile-install", "nexus-pack-sha256-v1:digest").
				WillReturnRows(test.rows)
			binding := catalogv1.IntegrationBinding{
				OwnerPack: "profile-owner", PackInstallationID: "profile-install",
				PackPayloadDigest: "nexus-pack-sha256-v1:digest",
			}
			err = requireExactActivePackGeneration(t.Context(), db, binding)
			if (err != nil) != test.wantErr {
				t.Fatalf("error = %v", err)
			}
			if err := mock.ExpectationsWereMet(); err != nil {
				t.Fatal(err)
			}
		})
	}
}

func TestAuthorityLoadRetryabilitySeparatesDriftFromTransientStorage(t *testing.T) {
	for name, test := range map[string]struct {
		err  error
		want bool
	}{
		"missing generation": {err: ErrDependency},
		"binding mismatch":   {err: ErrIdentityConflict},
		"missing profile":    {err: connector_callout.ErrProfileNotFound},
		"retired profile":    {err: connector_callout.ErrProfileUnavailable},
		"transient storage":  {err: errors.New("database temporarily unavailable"), want: true},
	} {
		t.Run(name, func(t *testing.T) {
			if got := authorityLoadRetryable(test.err); got != test.want {
				t.Fatalf("retryable = %v, want %v", got, test.want)
			}
		})
	}
}

func TestLoadExactPushContractPreservesTransientStorageError(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	storageErr := errors.New("database temporarily unavailable")
	mock.ExpectQuery("SELECT RuntimeStartupShallowDeclarations").
		WithArgs("profile-owner", "profile-install", "nexus-pack-sha256-v1:digest").
		WillReturnError(storageErr)
	binding := catalogv1.IntegrationBinding{
		OwnerPack: "profile-owner", PackInstallationID: "profile-install",
		PackPayloadDigest: "nexus-pack-sha256-v1:digest",
	}
	_, err = loadExactPushContract(t.Context(), db, binding)
	if !errors.Is(err, storageErr) {
		t.Fatalf("error = %v, want transient storage error", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatal(err)
	}
}
