package cluster

import (
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/pingcap-inc/clinic/pkg/auth/session"
	"github.com/pingcap-inc/clinic/pkg/datasource/view"
	"github.com/pingcap-inc/clinic/pkg/db"
	"github.com/pingcap-inc/clinic/pkg/o11y"
)

func TestListResourcePoolComponentsUsesTypedSources(t *testing.T) {
	user := &session.CtxUser{Internal: true}
	want := []*view.ResourcePoolComponent{{Id: "real", ComponentType: "tidb"}}

	tests := []struct {
		name               string
		cluster            *db.Cluster
		wantSource         string
		wantClusterID      uint64
		wantResourcePoolID uint64
	}{
		{
			name:          "dedicated",
			cluster:       &db.Cluster{ClusterID: "101", DeployTypeV2: o11y.DeployTypeV2Dedicated},
			wantSource:    "dedicated",
			wantClusterID: 101,
		},
		{
			name:          "resource pool",
			cluster:       &db.Cluster{ClusterID: "202", DeployTypeV2: o11y.DeployTypeV2PremiumResourcePool},
			wantSource:    "resource-pool",
			wantClusterID: 202,
		},
		{
			name:               "premium cluster",
			cluster:            &db.Cluster{ClusterID: "303", ParentID: "404", DeployTypeV2: o11y.DeployTypeV2Premium},
			wantSource:         "premium",
			wantClusterID:      303,
			wantResourcePoolID: 404,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			calledSource := ""
			var gotClusterID, gotResourcePoolID uint64
			sources := resourcePoolComponentSources{
				dedicated: func(gotUser *session.CtxUser, clusterID uint64) ([]*view.ResourcePoolComponent, error) {
					require.Same(t, user, gotUser)
					calledSource = "dedicated"
					gotClusterID = clusterID
					return want, nil
				},
				resourcePool: func(gotUser *session.CtxUser, clusterID uint64) ([]*view.ResourcePoolComponent, error) {
					require.Same(t, user, gotUser)
					calledSource = "resource-pool"
					gotClusterID = clusterID
					return want, nil
				},
				premium: func(gotUser *session.CtxUser, clusterID, resourcePoolID uint64) ([]*view.ResourcePoolComponent, error) {
					require.Same(t, user, gotUser)
					calledSource = "premium"
					gotClusterID = clusterID
					gotResourcePoolID = resourcePoolID
					return want, nil
				},
			}

			got, err := listResourcePoolComponents(user, tt.cluster, sources)
			require.NoError(t, err)
			require.Equal(t, want, got)
			require.Equal(t, tt.wantSource, calledSource)
			require.Equal(t, tt.wantClusterID, gotClusterID)
			require.Equal(t, tt.wantResourcePoolID, gotResourcePoolID)
			require.NotEqual(t, "mocked", got[len(got)-1].Id)
		})
	}
}

func TestLegacyMockedTiCDCCompatibilityIsExplicit(t *testing.T) {
	require.True(t, isLegacyMockedTiCDCCluster(o11y.DeployTypeV2Premium))
	require.False(t, isLegacyMockedTiCDCCluster(o11y.DeployTypeV2PremiumResourcePool))

	real := []*view.ResourcePoolComponent{{Id: "real", ComponentType: "tidb"}}
	got := appendLegacyMockedTiCDC(real)
	require.Len(t, got, 2)
	require.Equal(t, "real", got[0].Id)
	require.Equal(t, "mocked", got[1].Id)
	require.Equal(t, view.ComponentType("ticdc"), got[1].ComponentType)
}
