// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0

package controllers

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
	"sigs.k8s.io/controller-runtime/pkg/reconcile"

	mcpv1beta1 "github.com/stacklok/toolhive/cmd/thv-operator/api/v1beta1"
)

const (
	testGroupName = "test-group"
)

// TestMCPGroupReconciler_Reconcile_BasicLogic tests the core reconciliation logic
// using a fake client to avoid needing a real Kubernetes cluster
func TestMCPGroupReconciler_Reconcile_BasicLogic(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name                string
		mcpGroup            *mcpv1beta1.MCPGroup
		mcpServers          []*mcpv1beta1.MCPServer
		expectedServerCount int32
		expectedServerNames []string
		expectedPhase       mcpv1beta1.MCPGroupPhase
	}{
		{
			name: "group with two running servers should be ready",
			mcpGroup: &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      testGroupName,
					Namespace: "default",
				},
			},
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
					Status: mcpv1beta1.MCPServerStatus{
						Phase: mcpv1beta1.MCPServerPhaseReady,
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server2",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
					Status: mcpv1beta1.MCPServerStatus{
						Phase: mcpv1beta1.MCPServerPhaseReady,
					},
				},
			},
			expectedServerCount: 2,
			expectedServerNames: []string{"server1", "server2"},
			expectedPhase:       mcpv1beta1.MCPGroupPhaseReady,
		},
		{
			name: "group with servers regardless of status should be ready",
			mcpGroup: &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      testGroupName,
					Namespace: "default",
				},
			},
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
					Status: mcpv1beta1.MCPServerStatus{
						Phase: mcpv1beta1.MCPServerPhaseReady,
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server2",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
					Status: mcpv1beta1.MCPServerStatus{
						Phase: mcpv1beta1.MCPServerPhaseFailed,
					},
				},
			},
			expectedServerCount: 2,
			expectedServerNames: []string{"server1", "server2"},
			expectedPhase:       mcpv1beta1.MCPGroupPhaseReady, // Controller doesn't check individual server phases
		},
		{
			name: "group with mixed server phases should be ready",
			mcpGroup: &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      testGroupName,
					Namespace: "default",
				},
			},
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
					Status: mcpv1beta1.MCPServerStatus{
						Phase: mcpv1beta1.MCPServerPhaseReady,
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server2",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
					Status: mcpv1beta1.MCPServerStatus{
						Phase: mcpv1beta1.MCPServerPhasePending,
					},
				},
			},
			expectedServerCount: 2,
			expectedServerNames: []string{"server1", "server2"},
			expectedPhase:       mcpv1beta1.MCPGroupPhaseReady, // Controller doesn't check individual server phases
		},
		{
			name: "group with no servers should be ready",
			mcpGroup: &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      testGroupName,
					Namespace: "default",
				},
			},
			mcpServers:          []*mcpv1beta1.MCPServer{},
			expectedServerCount: 0,
			expectedServerNames: []string{},
			expectedPhase:       mcpv1beta1.MCPGroupPhaseReady,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			// Create fake client with objects
			objs := []client.Object{tt.mcpGroup}
			for _, server := range tt.mcpServers {
				objs = append(objs, server)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithStatusSubresource(&mcpv1beta1.MCPGroup{}).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			// Reconcile
			req := reconcile.Request{
				NamespacedName: types.NamespacedName{
					Name:      tt.mcpGroup.Name,
					Namespace: tt.mcpGroup.Namespace,
				},
			}

			// First reconcile adds the finalizer
			result, err := r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.True(t, result.RequeueAfter > 0, "Should requeue after adding finalizer")

			// Second reconcile processes normally
			result, err = r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.False(t, result.RequeueAfter > 0, "Should not requeue")

			// Check the updated MCPGroup
			var updatedGroup mcpv1beta1.MCPGroup
			err = fakeClient.Get(ctx, req.NamespacedName, &updatedGroup)
			require.NoError(t, err)

			assert.Equal(t, tt.expectedServerCount, updatedGroup.Status.ServerCount)
			assert.Equal(t, tt.expectedPhase, updatedGroup.Status.Phase)
			assert.ElementsMatch(t, tt.expectedServerNames, updatedGroup.Status.Servers)
		})
	}
}

// TestMCPGroupReconciler_ServerFiltering tests the logic for filtering servers by groupRef
func TestMCPGroupReconciler_ServerFiltering(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name                string
		groupName           string
		namespace           string
		mcpServers          []*mcpv1beta1.MCPServer
		expectedServerNames []string
		expectedCount       int32
	}{
		{
			name:      "filters servers by exact groupRef match",
			groupName: testGroupName,
			namespace: "default",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server1", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server2", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: "other-group"}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server3", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
			},
			expectedServerNames: []string{"server1", "server3"},
			expectedCount:       2,
		},
		{
			name:      "excludes servers without groupRef",
			groupName: testGroupName,
			namespace: "default",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server1", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server2", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test"},
				},
			},
			expectedServerNames: []string{"server1"},
			expectedCount:       1,
		},
		{
			name:      "excludes servers from different namespaces",
			groupName: testGroupName,
			namespace: "namespace-a",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server1", Namespace: "namespace-a"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server2", Namespace: "namespace-b"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
			},
			expectedServerNames: []string{"server1"},
			expectedCount:       1,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			mcpGroup := &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      tt.groupName,
					Namespace: tt.namespace,
				},
			}

			objs := []client.Object{mcpGroup}
			for _, server := range tt.mcpServers {
				objs = append(objs, server)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithStatusSubresource(&mcpv1beta1.MCPGroup{}).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			req := reconcile.Request{
				NamespacedName: types.NamespacedName{
					Name:      tt.groupName,
					Namespace: tt.namespace,
				},
			}

			// First reconcile adds the finalizer
			result, err := r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.True(t, result.RequeueAfter > 0, "Should requeue after adding finalizer")

			// Second reconcile processes normally
			result, err = r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.False(t, result.RequeueAfter > 0, "Should not requeue")

			var updatedGroup mcpv1beta1.MCPGroup
			err = fakeClient.Get(ctx, req.NamespacedName, &updatedGroup)
			require.NoError(t, err)

			assert.Equal(t, tt.expectedCount, updatedGroup.Status.ServerCount)
			assert.ElementsMatch(t, tt.expectedServerNames, updatedGroup.Status.Servers)
		})
	}
}

// TestMCPGroupReconciler_findMCPGroupForMCPServer tests the watch mapping function
func TestMCPGroupReconciler_findMCPGroupForMCPServer(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name              string
		mcpServer         *mcpv1beta1.MCPServer
		mcpGroups         []*mcpv1beta1.MCPGroup
		expectedRequests  int
		expectedGroupName string
	}{
		{
			name: "server with groupRef finds matching group",
			mcpServer: &mcpv1beta1.MCPServer{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-server",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPServerSpec{
					Image:    "test-image",
					GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      testGroupName,
						Namespace: "default",
					},
				},
			},
			expectedRequests:  1,
			expectedGroupName: testGroupName,
		},
		{
			name: "server without groupRef returns empty",
			mcpServer: &mcpv1beta1.MCPServer{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-server",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPServerSpec{
					Image: "test-image",
					// No GroupRef
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      testGroupName,
						Namespace: "default",
					},
				},
			},
			expectedRequests: 0,
		},
		{
			name: "server with non-existent groupRef returns empty",
			mcpServer: &mcpv1beta1.MCPServer{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-server",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPServerSpec{
					Image:    "test-image",
					GroupRef: &mcpv1beta1.MCPGroupRef{Name: "non-existent-group"},
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      testGroupName,
						Namespace: "default",
					},
				},
			},
			expectedRequests: 0,
		},
		{
			name: "server finds correct group among multiple groups",
			mcpServer: &mcpv1beta1.MCPServer{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-server",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPServerSpec{
					Image:    "test-image",
					GroupRef: &mcpv1beta1.MCPGroupRef{Name: "group-b"},
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "group-a",
						Namespace: "default",
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "group-b",
						Namespace: "default",
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "group-c",
						Namespace: "default",
					},
				},
			},
			expectedRequests:  1,
			expectedGroupName: "group-b",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			// Create fake client with objects
			objs := []client.Object{}
			for _, group := range tt.mcpGroups {
				objs = append(objs, group)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			requests := r.findMCPGroupForMCPServer(ctx, tt.mcpServer)

			assert.Len(t, requests, tt.expectedRequests)
			if tt.expectedRequests > 0 {
				assert.Equal(t, tt.expectedGroupName, requests[0].Name)
				assert.Equal(t, tt.mcpServer.Namespace, requests[0].Namespace)
			}
		})
	}
}

// TestMCPGroupReconciler_GroupNotFound tests handling of non-existent groups
func TestMCPGroupReconciler_GroupNotFound(t *testing.T) {
	t.Parallel()

	ctx := t.Context()
	scheme := runtime.NewScheme()
	require.NoError(t, mcpv1beta1.AddToScheme(scheme))
	require.NoError(t, corev1.AddToScheme(scheme))

	fakeClient := fake.NewClientBuilder().
		WithScheme(scheme).
		WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
			mcpServer := obj.(*mcpv1beta1.MCPServer)
			if mcpServer.Spec.GroupRef.GetName() == "" {
				return nil
			}
			return []string{mcpServer.Spec.GroupRef.GetName()}
		}).
		WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
			mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
			if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
				return nil
			}
			return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
		}).
		WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
			mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
			if mcpServerEntry.Spec.GroupRef.GetName() == "" {
				return nil
			}
			return []string{mcpServerEntry.Spec.GroupRef.GetName()}
		}).
		Build()

	r := &MCPGroupReconciler{
		Client: fakeClient,
	}

	// Reconcile a non-existent group
	req := reconcile.Request{
		NamespacedName: types.NamespacedName{
			Name:      "non-existent-group",
			Namespace: "default",
		},
	}

	result, err := r.Reconcile(ctx, req)
	require.NoError(t, err)
	assert.False(t, result.RequeueAfter > 0, "Should not requeue for non-existent group")
}

// TestMCPGroupReconciler_Conditions tests the MCPServersChecked condition
func TestMCPGroupReconciler_Conditions(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name                    string
		mcpGroup                *mcpv1beta1.MCPGroup
		mcpServers              []*mcpv1beta1.MCPServer
		expectedConditionStatus metav1.ConditionStatus
		expectedConditionReason string
		expectedPhase           mcpv1beta1.MCPGroupPhase
	}{
		{
			name: "MCPServersChecked condition is True when listing succeeds",
			mcpGroup: &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      testGroupName,
					Namespace: "default",
				},
			},
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
				},
			},
			expectedConditionStatus: metav1.ConditionTrue,
			expectedConditionReason: mcpv1beta1.ConditionReasonListMCPServersSucceeded,
			expectedPhase:           mcpv1beta1.MCPGroupPhaseReady,
		},
		{
			name: "MCPServersChecked condition is True even with no servers",
			mcpGroup: &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      testGroupName,
					Namespace: "default",
				},
			},
			mcpServers:              []*mcpv1beta1.MCPServer{},
			expectedConditionStatus: metav1.ConditionTrue,
			expectedConditionReason: mcpv1beta1.ConditionReasonListMCPServersSucceeded,
			expectedPhase:           mcpv1beta1.MCPGroupPhaseReady,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			objs := []client.Object{tt.mcpGroup}
			for _, server := range tt.mcpServers {
				objs = append(objs, server)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithStatusSubresource(&mcpv1beta1.MCPGroup{}).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			req := reconcile.Request{
				NamespacedName: types.NamespacedName{
					Name:      tt.mcpGroup.Name,
					Namespace: tt.mcpGroup.Namespace,
				},
			}

			// First reconcile adds the finalizer
			result, err := r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.True(t, result.RequeueAfter > 0, "Should requeue after adding finalizer")

			// Second reconcile processes normally
			result, err = r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.False(t, result.RequeueAfter > 0, "Should not requeue")

			var updatedGroup mcpv1beta1.MCPGroup
			err = fakeClient.Get(ctx, req.NamespacedName, &updatedGroup)
			require.NoError(t, err)

			assert.Equal(t, tt.expectedPhase, updatedGroup.Status.Phase)

			// Check the MCPServersChecked condition
			var condition *metav1.Condition
			for i := range updatedGroup.Status.Conditions {
				if updatedGroup.Status.Conditions[i].Type == mcpv1beta1.ConditionTypeMCPServersChecked {
					condition = &updatedGroup.Status.Conditions[i]
					break
				}
			}

			require.NotNil(t, condition, "MCPServersChecked condition should be present")
			assert.Equal(t, tt.expectedConditionStatus, condition.Status)
			if tt.expectedConditionReason != "" {
				assert.Equal(t, tt.expectedConditionReason, condition.Reason)
			}
		})
	}
}

// TestMCPGroupReconciler_Finalizer tests finalizer addition and behavior
func TestMCPGroupReconciler_Finalizer(t *testing.T) {
	t.Parallel()

	ctx := t.Context()
	scheme := runtime.NewScheme()
	require.NoError(t, mcpv1beta1.AddToScheme(scheme))
	require.NoError(t, corev1.AddToScheme(scheme))

	mcpGroup := &mcpv1beta1.MCPGroup{
		ObjectMeta: metav1.ObjectMeta{
			Name:      testGroupName,
			Namespace: "default",
		},
	}

	fakeClient := fake.NewClientBuilder().
		WithScheme(scheme).
		WithObjects(mcpGroup).
		WithStatusSubresource(&mcpv1beta1.MCPGroup{}, &mcpv1beta1.MCPServer{}).
		WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
			mcpServer := obj.(*mcpv1beta1.MCPServer)
			if mcpServer.Spec.GroupRef.GetName() == "" {
				return nil
			}
			return []string{mcpServer.Spec.GroupRef.GetName()}
		}).
		WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
			mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
			if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
				return nil
			}
			return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
		}).
		WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
			mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
			if mcpServerEntry.Spec.GroupRef.GetName() == "" {
				return nil
			}
			return []string{mcpServerEntry.Spec.GroupRef.GetName()}
		}).
		Build()

	r := &MCPGroupReconciler{
		Client: fakeClient,
	}

	req := reconcile.Request{
		NamespacedName: types.NamespacedName{
			Name:      mcpGroup.Name,
			Namespace: mcpGroup.Namespace,
		},
	}

	// First reconcile should add the finalizer
	result, err := r.Reconcile(ctx, req)
	require.NoError(t, err)
	assert.True(t, result.RequeueAfter > 0, "Should requeue after adding finalizer")

	// Verify finalizer was added
	var updatedGroup mcpv1beta1.MCPGroup
	err = fakeClient.Get(ctx, req.NamespacedName, &updatedGroup)
	require.NoError(t, err)
	assert.Contains(t, updatedGroup.Finalizers, MCPGroupFinalizerName)

	// Second reconcile should proceed with normal logic
	result, err = r.Reconcile(ctx, req)
	require.NoError(t, err)
	assert.False(t, result.RequeueAfter > 0, "Should not requeue")
}

// TestMCPGroupReconciler_Deletion tests deletion with finalizer cleanup
func TestMCPGroupReconciler_Deletion(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name                        string
		mcpServers                  []*mcpv1beta1.MCPServer
		expectedServerConditionType string
		shouldUpdateServers         bool
	}{
		{
			name: "deletion updates referencing servers",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server2",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
				},
			},
			expectedServerConditionType: mcpv1beta1.ConditionGroupRefValidated,
			shouldUpdateServers:         true,
		},
		{
			name: "deletion with no referencing servers succeeds",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "server1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPServerSpec{
						Image:    "test-image",
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: "other-group"},
					},
				},
			},
			shouldUpdateServers: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			// Create group with finalizer and deletion timestamp
			now := metav1.Now()
			mcpGroup := &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:              testGroupName,
					Namespace:         "default",
					Finalizers:        []string{MCPGroupFinalizerName},
					DeletionTimestamp: &now,
				},
			}

			objs := []client.Object{mcpGroup}
			for _, server := range tt.mcpServers {
				objs = append(objs, server)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithStatusSubresource(&mcpv1beta1.MCPGroup{}, &mcpv1beta1.MCPServer{}).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			req := reconcile.Request{
				NamespacedName: types.NamespacedName{
					Name:      mcpGroup.Name,
					Namespace: mcpGroup.Namespace,
				},
			}

			// Reconcile should handle deletion
			result, err := r.Reconcile(ctx, req)
			require.NoError(t, err)
			assert.False(t, result.RequeueAfter > 0, "Should not requeue on deletion")

			// Verify finalizer was removed (group might already be deleted by fake client)
			var updatedGroup mcpv1beta1.MCPGroup
			err = fakeClient.Get(ctx, req.NamespacedName, &updatedGroup)
			// If the group still exists, verify finalizer was removed
			if err == nil {
				assert.NotContains(t, updatedGroup.Finalizers, MCPGroupFinalizerName)
			}

			// If servers should be updated, verify their conditions
			if tt.shouldUpdateServers {
				for _, server := range tt.mcpServers {
					if server.Spec.GroupRef.GetName() == testGroupName {
						var updatedServer mcpv1beta1.MCPServer
						err = fakeClient.Get(ctx, types.NamespacedName{
							Name:      server.Name,
							Namespace: server.Namespace,
						}, &updatedServer)
						require.NoError(t, err)

						// Check that the GroupRefValidated condition was set to False
						var condition *metav1.Condition
						for i := range updatedServer.Status.Conditions {
							if updatedServer.Status.Conditions[i].Type == tt.expectedServerConditionType {
								condition = &updatedServer.Status.Conditions[i]
								break
							}
						}

						require.NotNil(t, condition, "GroupRefValidated condition should be present")
						assert.Equal(t, metav1.ConditionFalse, condition.Status)
						assert.Equal(t, mcpv1beta1.ConditionReasonGroupRefNotFound, condition.Reason)
						assert.Contains(t, condition.Message, "being deleted")
					}
				}
			}
		})
	}
}

// TestMCPGroupReconciler_findReferencingMCPServers tests finding servers that reference a group
func TestMCPGroupReconciler_findReferencingMCPServers(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name          string
		groupName     string
		namespace     string
		mcpServers    []*mcpv1beta1.MCPServer
		expectedCount int
		expectedNames []string
	}{
		{
			name:      "finds servers with matching groupRef",
			groupName: testGroupName,
			namespace: "default",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server1", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server2", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: "other-group"}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server3", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
			},
			expectedCount: 2,
			expectedNames: []string{"server1", "server3"},
		},
		{
			name:      "returns empty when no servers reference the group",
			groupName: testGroupName,
			namespace: "default",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server1", Namespace: "default"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: "other-group"}},
				},
			},
			expectedCount: 0,
			expectedNames: []string{},
		},
		{
			name:      "excludes servers from different namespaces",
			groupName: testGroupName,
			namespace: "namespace-a",
			mcpServers: []*mcpv1beta1.MCPServer{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server1", Namespace: "namespace-a"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "server2", Namespace: "namespace-b"},
					Spec:       mcpv1beta1.MCPServerSpec{Image: "test", GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
			},
			expectedCount: 1,
			expectedNames: []string{"server1"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			mcpGroup := &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      tt.groupName,
					Namespace: tt.namespace,
				},
			}

			objs := []client.Object{}
			for _, server := range tt.mcpServers {
				objs = append(objs, server)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			servers, err := r.findReferencingMCPServers(ctx, mcpGroup)
			require.NoError(t, err)
			assert.Len(t, servers, tt.expectedCount)

			if tt.expectedCount > 0 {
				serverNames := make([]string, len(servers))
				for i, s := range servers {
					serverNames[i] = s.Name
				}
				assert.ElementsMatch(t, tt.expectedNames, serverNames)
			}
		})
	}
}

// TestMCPGroupReconciler_findReferencingMCPRemoteProxies tests finding remote proxies that reference a group
func TestMCPGroupReconciler_findReferencingMCPRemoteProxies(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name             string
		groupName        string
		namespace        string
		mcpRemoteProxies []*mcpv1beta1.MCPRemoteProxy
		expectedCount    int
		expectedNames    []string
	}{
		{
			name:      "finds remote proxies with matching groupRef",
			groupName: testGroupName,
			namespace: "default",
			mcpRemoteProxies: []*mcpv1beta1.MCPRemoteProxy{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "proxy1", Namespace: "default"},
					Spec:       mcpv1beta1.MCPRemoteProxySpec{GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "proxy2", Namespace: "default"},
					Spec:       mcpv1beta1.MCPRemoteProxySpec{GroupRef: &mcpv1beta1.MCPGroupRef{Name: "other-group"}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "proxy3", Namespace: "default"},
					Spec:       mcpv1beta1.MCPRemoteProxySpec{GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
			},
			expectedCount: 2,
			expectedNames: []string{"proxy1", "proxy3"},
		},
		{
			name:      "returns empty when no remote proxies reference the group",
			groupName: testGroupName,
			namespace: "default",
			mcpRemoteProxies: []*mcpv1beta1.MCPRemoteProxy{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "proxy1", Namespace: "default"},
					Spec:       mcpv1beta1.MCPRemoteProxySpec{GroupRef: &mcpv1beta1.MCPGroupRef{Name: "other-group"}},
				},
			},
			expectedCount: 0,
			expectedNames: []string{},
		},
		{
			name:      "excludes remote proxies from different namespaces",
			groupName: testGroupName,
			namespace: "namespace-a",
			mcpRemoteProxies: []*mcpv1beta1.MCPRemoteProxy{
				{
					ObjectMeta: metav1.ObjectMeta{Name: "proxy1", Namespace: "namespace-a"},
					Spec:       mcpv1beta1.MCPRemoteProxySpec{GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
				{
					ObjectMeta: metav1.ObjectMeta{Name: "proxy2", Namespace: "namespace-b"},
					Spec:       mcpv1beta1.MCPRemoteProxySpec{GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName}},
				},
			},
			expectedCount: 1,
			expectedNames: []string{"proxy1"},
		},
		{
			name:             "returns empty when no remote proxies exist",
			groupName:        testGroupName,
			namespace:        "default",
			mcpRemoteProxies: []*mcpv1beta1.MCPRemoteProxy{},
			expectedCount:    0,
			expectedNames:    []string{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			mcpGroup := &mcpv1beta1.MCPGroup{
				ObjectMeta: metav1.ObjectMeta{
					Name:      tt.groupName,
					Namespace: tt.namespace,
				},
			}

			objs := []client.Object{}
			for _, proxy := range tt.mcpRemoteProxies {
				objs = append(objs, proxy)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			proxies, err := r.findReferencingMCPRemoteProxies(ctx, mcpGroup)
			require.NoError(t, err)
			assert.Len(t, proxies, tt.expectedCount)

			if tt.expectedCount > 0 {
				proxyNames := make([]string, len(proxies))
				for i, p := range proxies {
					proxyNames[i] = p.Name
				}
				assert.ElementsMatch(t, tt.expectedNames, proxyNames)
			}
		})
	}
}

// TestMCPGroupReconciler_findMCPGroupForMCPRemoteProxy tests the watch mapping function for remote proxies
func TestMCPGroupReconciler_findMCPGroupForMCPRemoteProxy(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name              string
		mcpRemoteProxy    *mcpv1beta1.MCPRemoteProxy
		mcpGroups         []*mcpv1beta1.MCPGroup
		expectedRequests  int
		expectedGroupName string
	}{
		{
			name: "remote proxy with groupRef finds matching group",
			mcpRemoteProxy: &mcpv1beta1.MCPRemoteProxy{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-proxy",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPRemoteProxySpec{
					GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      testGroupName,
						Namespace: "default",
					},
				},
			},
			expectedRequests:  1,
			expectedGroupName: testGroupName,
		},
		{
			name: "remote proxy without groupRef returns empty",
			mcpRemoteProxy: &mcpv1beta1.MCPRemoteProxy{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-proxy",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPRemoteProxySpec{
					// No GroupRef
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      testGroupName,
						Namespace: "default",
					},
				},
			},
			expectedRequests: 0,
		},
		{
			name: "remote proxy with non-existent groupRef returns empty",
			mcpRemoteProxy: &mcpv1beta1.MCPRemoteProxy{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-proxy",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPRemoteProxySpec{
					GroupRef: &mcpv1beta1.MCPGroupRef{Name: "non-existent-group"},
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      testGroupName,
						Namespace: "default",
					},
				},
			},
			expectedRequests: 0,
		},
		{
			name: "remote proxy finds correct group among multiple groups",
			mcpRemoteProxy: &mcpv1beta1.MCPRemoteProxy{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test-proxy",
					Namespace: "default",
				},
				Spec: mcpv1beta1.MCPRemoteProxySpec{
					GroupRef: &mcpv1beta1.MCPGroupRef{Name: "group-b"},
				},
			},
			mcpGroups: []*mcpv1beta1.MCPGroup{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "group-a",
						Namespace: "default",
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "group-b",
						Namespace: "default",
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "group-c",
						Namespace: "default",
					},
				},
			},
			expectedRequests:  1,
			expectedGroupName: "group-b",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			// Create fake client with objects
			objs := []client.Object{}
			for _, group := range tt.mcpGroups {
				objs = append(objs, group)
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			requests := r.findMCPGroupForMCPRemoteProxy(ctx, tt.mcpRemoteProxy)

			assert.Len(t, requests, tt.expectedRequests)
			if tt.expectedRequests > 0 {
				assert.Equal(t, tt.expectedGroupName, requests[0].Name)
				assert.Equal(t, tt.mcpRemoteProxy.Namespace, requests[0].Namespace)
			}
		})
	}
}

// TestMCPGroupReconciler_updateReferencingRemoteProxiesOnDeletion tests updating remote proxy conditions during group deletion
func TestMCPGroupReconciler_updateReferencingRemoteProxiesOnDeletion(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name             string
		groupName        string
		mcpRemoteProxies []mcpv1beta1.MCPRemoteProxy
		expectedUpdates  int
	}{
		{
			name:      "updates conditions on remote proxies",
			groupName: testGroupName,
			mcpRemoteProxies: []mcpv1beta1.MCPRemoteProxy{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "proxy1",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPRemoteProxySpec{
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
				},
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "proxy2",
						Namespace: "default",
					},
					Spec: mcpv1beta1.MCPRemoteProxySpec{
						GroupRef: &mcpv1beta1.MCPGroupRef{Name: testGroupName},
					},
				},
			},
			expectedUpdates: 2,
		},
		{
			name:             "handles empty proxy list",
			groupName:        testGroupName,
			mcpRemoteProxies: []mcpv1beta1.MCPRemoteProxy{},
			expectedUpdates:  0,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			ctx := t.Context()
			scheme := runtime.NewScheme()
			require.NoError(t, mcpv1beta1.AddToScheme(scheme))
			require.NoError(t, corev1.AddToScheme(scheme))

			objs := []client.Object{}
			for i := range tt.mcpRemoteProxies {
				objs = append(objs, &tt.mcpRemoteProxies[i])
			}

			fakeClient := fake.NewClientBuilder().
				WithScheme(scheme).
				WithObjects(objs...).
				WithStatusSubresource(&mcpv1beta1.MCPRemoteProxy{}).
				WithIndex(&mcpv1beta1.MCPServer{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServer := obj.(*mcpv1beta1.MCPServer)
					if mcpServer.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServer.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPRemoteProxy{}, "spec.groupRef", func(obj client.Object) []string {
					mcpRemoteProxy := obj.(*mcpv1beta1.MCPRemoteProxy)
					if mcpRemoteProxy.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpRemoteProxy.Spec.GroupRef.GetName()}
				}).
				WithIndex(&mcpv1beta1.MCPServerEntry{}, "spec.groupRef", func(obj client.Object) []string {
					mcpServerEntry := obj.(*mcpv1beta1.MCPServerEntry)
					if mcpServerEntry.Spec.GroupRef.GetName() == "" {
						return nil
					}
					return []string{mcpServerEntry.Spec.GroupRef.GetName()}
				}).
				Build()

			r := &MCPGroupReconciler{
				Client: fakeClient,
			}

			// Call the function under test
			r.updateReferencingRemoteProxiesOnDeletion(ctx, tt.mcpRemoteProxies, tt.groupName)

			// Verify that the proxies have been updated with the correct condition
			for _, proxy := range tt.mcpRemoteProxies {
				updatedProxy := &mcpv1beta1.MCPRemoteProxy{}
				err := fakeClient.Get(ctx, types.NamespacedName{
					Name:      proxy.Name,
					Namespace: proxy.Namespace,
				}, updatedProxy)
				require.NoError(t, err)

				// Check that the GroupRefValidated condition is set to False
				condition := meta.FindStatusCondition(updatedProxy.Status.Conditions,
					mcpv1beta1.ConditionTypeMCPRemoteProxyGroupRefValidated)
				require.NotNil(t, condition, "Expected condition %s to be set",
					mcpv1beta1.ConditionTypeMCPRemoteProxyGroupRefValidated)
				assert.Equal(t, metav1.ConditionFalse, condition.Status)
				assert.Equal(t, mcpv1beta1.ConditionReasonMCPRemoteProxyGroupRefNotFound, condition.Reason)
				assert.Contains(t, condition.Message, "being deleted")
			}
		})
	}
}
