package registry

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestRegisterBuiltin_ConnectionPolicy(t *testing.T) {
	t.Run("default required preserves digest", func(t *testing.T) {
		def := makeBuiltinDefinition(t, "demo", 1, "do-thing", "summary one")

		legacy, err := New().RegisterBuiltin(def, fakeExecutor{}, "rev-1")
		require.NoError(t, err)
		explicit, err := New().RegisterBuiltinWithOptions(
			def,
			fakeExecutor{},
			"rev-1",
			BuiltinOptions{ConnectionPolicy: ConnectionRequired},
		)
		require.NoError(t, err)

		assert.Equal(t, legacy.Definition.Digest, explicit.Definition.Digest)
		assert.Equal(t, ConnectionRequired, legacy.ConnectionPolicy)
		assert.Equal(t, ConnectionRequired, explicit.ConnectionPolicy)
	})

	t.Run("none is digest pinned and clone on read", func(t *testing.T) {
		r := New()
		def := makeBuiltinDefinition(t, "demo", 1, "do-thing", "summary one")

		connectionless, err := r.RegisterBuiltinWithOptions(
			def,
			fakeExecutor{},
			"rev-1",
			BuiltinOptions{ConnectionPolicy: ConnectionNone},
		)
		require.NoError(t, err)
		required, err := New().RegisterBuiltin(def, fakeExecutor{}, "rev-1")
		require.NoError(t, err)
		require.NotEqual(
			t,
			required.Definition.Digest,
			connectionless.Definition.Digest,
		)
		assert.Equal(t, ConnectionNone, connectionless.ConnectionPolicy)

		lookup, ok := r.LookupByDigest(connectionless.Definition.Digest)
		require.True(t, ok)
		assert.Equal(t, ConnectionNone, lookup.ConnectionPolicy)
	})

	t.Run("policy change conflicts at identity", func(t *testing.T) {
		r := New()
		def := makeBuiltinDefinition(t, "demo", 1, "do-thing", "summary one")
		_, err := r.RegisterBuiltin(def, fakeExecutor{}, "rev-1")
		require.NoError(t, err)

		_, err = r.RegisterBuiltinWithOptions(
			def,
			fakeExecutor{},
			"rev-1",
			BuiltinOptions{ConnectionPolicy: ConnectionNone},
		)
		var conflict *ConflictError
		require.ErrorAs(t, err, &conflict)
	})

	t.Run("invalid rejected", func(t *testing.T) {
		def := makeBuiltinDefinition(t, "demo", 1, "do-thing", "summary one")
		_, err := New().RegisterBuiltinWithOptions(
			def,
			fakeExecutor{},
			"rev-1",
			BuiltinOptions{ConnectionPolicy: ConnectionPolicy(99)},
		)
		require.ErrorIs(t, err, ErrInvalidConnectionPolicy)
	})
}
