package tidbmanager

import (
	"context"
	"errors"
	"testing"

	. "github.com/onsi/gomega"
	"github.com/tidbcloud/aws-shared-provider/cmd/manager/app/config"
	"github.com/tidbcloud/aws-shared-provider/pkg/utils/tidb"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	infraapi "github.com/tidbcloud/tidb-management-service/api/serverless_infra"
	infraclientfake "github.com/tidbcloud/tidb-management-service/api/serverless_infra/client/fake"
	"github.com/tidbcloud/tidb-management-service/api/serverless_infra/meta"
)

type fakeReplaceInfraAPI struct{}

func (f *fakeReplaceInfraAPI) GetBranch(ctx context.Context, namespace, name string) (*cloudv1.Branch, error) {
	return nil, errors.New("unexpected GetBranch call")
}

func (f *fakeReplaceInfraAPI) GetBranchWithToken(ctx context.Context, token string) (*cloudv1.Branch, error) {
	return nil, errors.New("unexpected GetBranchWithToken call")
}

func (f *fakeReplaceInfraAPI) PatchBranch(ctx context.Context, namespace, name string, data []byte) (*cloudv1.Branch, error) {
	return nil, errors.New("unexpected PatchBranch call")
}

func (f *fakeReplaceInfraAPI) Start(ctx context.Context) error {
	return nil
}

func (f *fakeReplaceInfraAPI) WaitForCacheSync(ctx context.Context) bool {
	return true
}

func Test_tidbManager_getActivateParameterIncludesKeyspaceID(t *testing.T) {
	g := NewGomegaWithT(t)

	cluster := &infraapi.Cluster{
		ObjectMeta: meta.ObjectMeta{
			Namespace:      "infra-ns",
			Name:           "cluster-1",
			TagsKubernetes: "test-cluster",
			TagsTenant:     "tenant-1",
			TagsProject:    "project-1",
		},
		Spec: infraapi.ClusterSpec{
			AuditLogConfig: infraapi.AuditLogConfig{
				Enabled:    true,
				Unredacted: false,
			},
		},
		Status: infraapi.ClusterStatus{
			Phase:         infraapi.ClusterPhaseRunning,
			KeyspaceToken: "token-1",
			KeyspaceId:    42,
			TidbPool:      "tidb-pool",
		},
	}

	infraClusterCli := &infraclientfake.Client{
		GetIndexFunc: func(value any, index string, dst any) error {
			g.Expect(value).To(Equal("token-1"))
			g.Expect(index).To(Equal("status.keyspace_token-index"))

			key, ok := dst.(*meta.ObjectKey)
			g.Expect(ok).To(BeTrue())
			key.Namespace = cluster.Namespace
			key.Name = cluster.Name
			return nil
		},
		GetFunc: func(obj infraapi.Object) error {
			got, ok := obj.(*infraapi.Cluster)
			g.Expect(ok).To(BeTrue())
			*got = *cluster.DeepCopy()
			return nil
		},
		PatchFunc:       func(set map[string]any, obj infraapi.Object) error { return nil },
		CreateFunc:      func(obj infraapi.Object) error { return nil },
		UpdateFunc:      func(obj infraapi.Object) error { return nil },
		DeleteFunc:      func(obj infraapi.Object, force bool) error { return nil },
		RangeFunc:       func(fn func(obj infraapi.Object) error) error { return nil },
		ForceUpdateFunc: func(obj infraapi.Object, deleted bool) error { return nil },
	}

	mgr := &tidbManager{
		infraClusterCli: infraClusterCli,
		infraApi:        &fakeReplaceInfraAPI{},
		cfg: &config.Config{
			KubeClusterName: "test-cluster",
		},
	}

	param, err := mgr.getActivateParameter(context.Background(), "token-1")
	g.Expect(err).NotTo(HaveOccurred())
	g.Expect(param).To(Equal(&tidb.ActivateParameter{
		EnableAuditLog:   true,
		AuditLogRedacted: true,
		MaxIdleSeconds:   0,
		KeyspaceID:       "42",
		TenantID:         "tenant-1",
		ClusterID:        "cluster-1",
		ProjectID:        "project-1",
	}))
}
