package client

import (
	"context"
	"database/sql"
	"encoding/json"
	"testing"
	"time"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/go-logr/logr"
	prometheusv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	v1 "github.com/tidbcloud/observability/api/regionalserver/resourceworker/v1"
	"github.com/tidbcloud/observability/pkg/common/constants"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/intstr"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

// setupMockDB creates a mock database and gorm.DB instance for testing
func setupMockDB(t *testing.T) (*sql.DB, sqlmock.Sqlmock, *gorm.DB) {
	sqlDB, mock, err := sqlmock.New()
	require.NoError(t, err)

	gormDB, err := gorm.Open(mysql.New(mysql.Config{
		Conn:                      sqlDB,
		SkipInitializeWithVersion: true,
	}), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	require.NoError(t, err)

	return sqlDB, mock, gormDB
}

// createTestCluster creates a test Cluster object
func createTestCluster() *v1.Cluster {
	return &v1.Cluster{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "observability.pingcap.com/v1",
			Kind:       "Cluster",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      "test-cluster",
			Namespace: "default",
			Labels: map[string]string{
				constants.LabelRegion:        "us-west-2",
				constants.LabelTenantID:      "tenant-1",
				constants.LabelProjectID:     "project-1",
				constants.LabelApplicationID: "app-1",
				constants.LabelBizType:       "dedicated",
			},
			Annotations: map[string]string{
				"test-annotation": "test-value",
			},
			ResourceVersion: "1",
		},
		Spec: v1.ClusterSpec{
			Endpoint: v1.Endpoint{
				Name:    "test-endpoint",
				UserARN: "arn:aws:iam::123456789012:user/test",
				Shared:  false,
			},
			VictoriaAccount: v1.VictoriaAccount{
				AccountID:         100,
				ProjectID:         200,
				SupportServerless: true,
				VMClusterName:     "vm-cluster-1",
				AvailabilityZone:  "us-west-2a",
				AlertResources: corev1.ResourceRequirements{
					Requests: corev1.ResourceList{
						corev1.ResourceCPU:    resource.MustParse("100m"),
						corev1.ResourceMemory: resource.MustParse("128Mi"),
					},
					Limits: corev1.ResourceList{
						corev1.ResourceCPU:    resource.MustParse("200m"),
						corev1.ResourceMemory: resource.MustParse("256Mi"),
					},
				},
			},
			MuteAlert: false,
		},
		Status: v1.ClusterStatus{
			Phase:    constants.ACTIVE,
			DnsName:  "test-cluster.example.com",
			UpdateAt: "2024-01-01T00:00:00Z",
		},
	}
}

func TestNewMySQLClient(t *testing.T) {
	t.Run("creates client successfully", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		mock.ExpectPing()

		// Reset global DB for test
		mu.Lock()
		globalDB = nil
		mu.Unlock()

		client := &mysqlClient{
			db:            gormDB,
			componentName: "test-component",
			eventTTL:      10 * time.Minute,
		}

		assert.NotNil(t, client)
		assert.Equal(t, "test-component", client.componentName)
		assert.Equal(t, 10*time.Minute, client.eventTTL)
	})
}

func TestGet(t *testing.T) {
	t.Run("successfully gets cluster", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		clusterID := "test-cluster"
		now := time.Now()

		// Mock transaction begin
		mock.ExpectBegin()

		// Mock cluster query - GORM adds LIMIT clause
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "region", "biz_type", "tenant", "project_id", "application_id",
			"creation_timestamp", "update_timestamp", "deletion_timestamp",
		}).AddRow(
			clusterID, "default", "us-west-2", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(clusterID, 1).
			WillReturnRows(clusterRows)

		// Mock spec query
		labelsJSON, _ := json.Marshal(map[string]string{"key": "value"})
		annotationsJSON, _ := json.Marshal(map[string]string{"anno": "value"})
		specRows := sqlmock.NewRows([]string{
			"cluster_id", "labels", "annotations",
			"endpoint_service_name", "endpoint_service_user_arn", "endpoint_service_shared",
			"mute_alert", "vm_account_id", "vm_project_id", "vm_support_serverless",
			"vm_cluster_name", "vm_availability_zone", "vm_rule_selector",
			"vm_alert_cpu_request", "vm_alert_cpu_limit", "vm_alert_memory_request", "vm_alert_memory_limit",
			"vm_alert_managers", "vmalert_max_queue_size", "creation_timestamp", "update_timestamp",
		}).AddRow(
			clusterID, labelsJSON, annotationsJSON,
			"endpoint", "arn", false,
			false, 100, 200, true,
			"vm-cluster", "us-west-2a", "{}",
			"100m", "200m", "128Mi", "256Mi",
			"[]", 0, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_specs`").
			WithArgs(clusterID).
			WillReturnRows(specRows)

		// Mock status query
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "phase", "dns_name", "update_at", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(
			clusterID, "Running", "test.example.com", "2024-01-01", 1, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(clusterID).
			WillReturnRows(statusRows)

		// Mock commit
		mock.ExpectCommit()

		obj := &v1.Cluster{}
		err := c.Get(context.Background(), client.ObjectKey{Name: clusterID}, obj)

		assert.NoError(t, err)
		assert.Equal(t, clusterID, obj.Name)
		assert.Equal(t, "default", obj.Namespace)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns not found error", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectBegin()
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnError(gorm.ErrRecordNotFound)
		mock.ExpectRollback()

		obj := &v1.Cluster{}
		err := c.Get(context.Background(), client.ObjectKey{Name: "nonexistent"}, obj)

		assert.True(t, apierrors.IsNotFound(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error for empty cluster ID", func(t *testing.T) {
		_, _, gormDB := setupMockDB(t)
		c := &mysqlClient{db: gormDB, componentName: "test"}

		obj := &v1.Cluster{}
		err := c.Get(context.Background(), client.ObjectKey{Name: ""}, obj)

		assert.ErrorIs(t, err, ErrObjkeyInvalid)
	})
}

func TestCreate(t *testing.T) {
	t.Run("successfully creates cluster", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		// Mock check for existing cluster
		mock.ExpectQuery("SELECT count\\(\\*\\) FROM `clusters`").
			WithArgs(cluster.Name).
			WillReturnRows(sqlmock.NewRows([]string{"count(*)"}).AddRow(0))

		// Mock cluster insert - GORM will insert cluster, spec, and status together
		mock.ExpectExec("INSERT INTO `clusters`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		// Mock spec insert (GORM handles associations)
		mock.ExpectExec("INSERT INTO `cluster_specs`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		// Mock status insert (GORM handles associations)
		mock.ExpectExec("INSERT INTO `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		// Mock event insert
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		mock.ExpectCommit()

		err := c.Create(context.Background(), cluster)

		assert.NoError(t, err)
		assert.Equal(t, "1", cluster.ResourceVersion)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns already exists error", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		// Mock check for existing cluster - returns 1
		mock.ExpectQuery("SELECT count\\(\\*\\) FROM `clusters`").
			WithArgs(cluster.Name).
			WillReturnRows(sqlmock.NewRows([]string{"count(*)"}).AddRow(1))

		mock.ExpectRollback()

		err := c.Create(context.Background(), cluster)

		assert.True(t, apierrors.IsAlreadyExists(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestUpdate(t *testing.T) {
	t.Run("successfully updates cluster", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()
		cluster.ResourceVersion = "1"

		mock.ExpectBegin()

		// Mock get current status for version check - GORM adds LIMIT clause
		now := time.Now()
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		// Mock cluster update
		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock spec update
		mock.ExpectExec("UPDATE `cluster_specs`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock status update with version check
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock event insert
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		mock.ExpectCommit()

		err := c.Update(context.Background(), cluster)

		assert.NoError(t, err)
		assert.Equal(t, "2", cluster.ResourceVersion)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns conflict error on version mismatch", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()
		cluster.ResourceVersion = "1"

		mock.ExpectBegin()

		// Mock get current status with different version - GORM adds LIMIT clause
		now := time.Now()
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 2, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectRollback()

		err := c.Update(context.Background(), cluster)

		assert.True(t, apierrors.IsConflict(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns not found error", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WillReturnError(gorm.ErrRecordNotFound)

		mock.ExpectRollback()

		err := c.Update(context.Background(), cluster)

		assert.True(t, apierrors.IsNotFound(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestDelete(t *testing.T) {
	t.Run("soft delete cluster", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		// Mock get cluster - GORM adds LIMIT clause
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, nil)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		// Mock get status for version - GORM adds LIMIT clause
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		// Mock soft delete (update deletion_timestamp)
		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock resource version update
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock event insert
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		mock.ExpectCommit()

		err := c.Delete(context.Background(), cluster)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("force delete cluster", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test", eventTTL: 10 * time.Minute}
		cluster := createTestCluster()
		deletionTime := metav1.Now()
		cluster.DeletionTimestamp = &deletionTime

		mock.ExpectBegin()

		// Mock get cluster with deletion timestamp - GORM adds LIMIT clause
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, deletionTime.Time)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		// Mock get status for version - GORM adds LIMIT clause
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		// Mock hard delete
		mock.ExpectExec("DELETE FROM `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock event insert with TTL
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnResult(sqlmock.NewResult(1, 1))

		mock.ExpectCommit()

		err := c.Delete(context.Background(), cluster, WithForce(func() {}))

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns not found error", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnError(gorm.ErrRecordNotFound)

		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster)

		assert.True(t, apierrors.IsNotFound(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestList(t *testing.T) {
	t.Run("successfully lists clusters", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		now := time.Now()
		labelsJSON, _ := json.Marshal(map[string]string{"key": "value"})
		annotationsJSON, _ := json.Marshal(map[string]string{"anno": "value"})

		// Mock cluster query
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "region", "biz_type", "tenant", "project_id", "application_id",
			"creation_timestamp", "update_timestamp", "deletion_timestamp",
		}).AddRow(
			"cluster-1", "default", "us-west-2", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		).AddRow(
			"cluster-2", "default", "us-east-1", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		)

		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnRows(clusterRows)

		// Mock spec queries - GORM loads Spec first
		specRows := sqlmock.NewRows([]string{
			"cluster_id", "labels", "annotations",
			"endpoint_service_name", "endpoint_service_user_arn", "endpoint_service_shared",
			"mute_alert", "vm_account_id", "vm_project_id", "vm_support_serverless",
			"vm_cluster_name", "vm_availability_zone", "vm_rule_selector",
			"vm_alert_cpu_request", "vm_alert_cpu_limit", "vm_alert_memory_request", "vm_alert_memory_limit",
			"vm_alert_managers", "vmalert_max_queue_size", "creation_timestamp", "update_timestamp",
		}).AddRow(
			"cluster-1", labelsJSON, annotationsJSON,
			"endpoint", "arn", false,
			false, 100, 200, true,
			"vm-cluster", "us-west-2a", "{}",
			"100m", "200m", "128Mi", "256Mi",
			"[]", 0, now, now,
		).AddRow(
			"cluster-2", labelsJSON, annotationsJSON,
			"endpoint", "arn", false,
			false, 100, 200, true,
			"vm-cluster", "us-west-2a", "{}",
			"100m", "200m", "128Mi", "256Mi",
			"[]", 0, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_specs`").
			WillReturnRows(specRows)

		// Mock status queries - GORM loads Status second
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "phase", "dns_name", "update_at", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(
			"cluster-1", "Running", "test.example.com", "2024-01-01", 1, now, now,
		).AddRow(
			"cluster-2", "Running", "test.example.com", "2024-01-01", 1, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WillReturnRows(statusRows)

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list)

		assert.NoError(t, err)
		assert.Len(t, list.Items, 2)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("lists with namespace filter", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectQuery("SELECT .* FROM `clusters` WHERE namespace = \\?").
			WithArgs("test-namespace").
			WillReturnRows(sqlmock.NewRows([]string{"cluster_id"}))

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list, client.InNamespace("test-namespace"))

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("lists with label selector", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		// Use a custom label that will trigger JSON_EXTRACT
		selector, _ := labels.Parse("tenant=tenant-1")

		// GORM will use JSON_EXTRACT for non-indexed labels and join with cluster_specs
		mock.ExpectQuery("SELECT .* FROM `clusters` LEFT JOIN cluster_specs").
			WillReturnRows(sqlmock.NewRows([]string{"cluster_id"}))

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list, client.MatchingLabelsSelector{Selector: selector})

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestPatch(t *testing.T) {
	t.Run("successfully patches cluster with merge patch", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		// Mock Get operation
		mock.ExpectBegin()
		now := time.Now()
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "region", "biz_type", "tenant", "project_id", "application_id",
			"creation_timestamp", "update_timestamp", "deletion_timestamp",
		}).AddRow(
			cluster.Name, "default", "us-west-2", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnRows(clusterRows)

		labelsJSON, _ := json.Marshal(map[string]string{"key": "value"})
		annotationsJSON, _ := json.Marshal(map[string]string{"anno": "value"})
		specRows := sqlmock.NewRows([]string{
			"cluster_id", "labels", "annotations",
			"endpoint_service_name", "endpoint_service_user_arn", "endpoint_service_shared",
			"mute_alert", "vm_account_id", "vm_project_id", "vm_support_serverless",
			"vm_cluster_name", "vm_availability_zone", "vm_rule_selector",
			"vm_alert_cpu_request", "vm_alert_cpu_limit", "vm_alert_memory_request", "vm_alert_memory_limit",
			"vm_alert_managers", "vmalert_max_queue_size", "creation_timestamp", "update_timestamp",
		}).AddRow(
			cluster.Name, labelsJSON, annotationsJSON,
			"endpoint", "arn", false,
			false, 100, 200, true,
			"vm-cluster", "us-west-2a", "{}",
			"100m", "200m", "128Mi", "256Mi",
			"[]", 0, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_specs`").
			WillReturnRows(specRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "phase", "dns_name", "update_at", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(
			cluster.Name, "Running", "test.example.com", "2024-01-01", 1, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WillReturnRows(statusRows)
		mock.ExpectCommit()

		// Mock Update operation
		mock.ExpectBegin()
		statusRows2 := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WillReturnRows(statusRows2)
		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_specs`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnResult(sqlmock.NewResult(1, 1))
		mock.ExpectCommit()

		patchData := []byte(`{"spec":{"muteAlert":true}}`)
		patch := client.RawPatch(types.MergePatchType, patchData)

		err := c.Patch(context.Background(), cluster, patch)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestStatusWriter(t *testing.T) {
	t.Run("successfully updates status", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		// Status writer uses WithContext which may trigger transaction in some GORM versions
		mock.ExpectBegin()
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectCommit()

		statusWriter := c.Status()
		err := statusWriter.Update(context.Background(), cluster)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestConvertK8sToCluster(t *testing.T) {
	t.Run("successfully converts K8s cluster to database records", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}
		k8sCluster := createTestCluster()

		cluster, spec, status, err := c.convertK8sToCluster(k8sCluster, false)

		assert.NoError(t, err)
		assert.NotNil(t, cluster)
		assert.NotNil(t, spec)
		assert.NotNil(t, status)

		// Verify cluster fields
		assert.Equal(t, k8sCluster.Name, cluster.ClusterID)
		assert.Equal(t, k8sCluster.Namespace, cluster.Namespace)
		assert.Equal(t, "us-west-2", cluster.Region)
		assert.Equal(t, "tenant-1", cluster.Tenant)
		assert.Equal(t, "project-1", cluster.ProjectID)
		assert.Equal(t, "app-1", cluster.ApplicationID)
		assert.Equal(t, "dedicated", cluster.BizType)

		// Verify spec fields
		assert.Equal(t, k8sCluster.Name, spec.ClusterID)
		assert.Equal(t, k8sCluster.Labels, spec.Labels)
		assert.Equal(t, k8sCluster.Annotations, spec.Annotations)
		assert.Equal(t, "test-endpoint", spec.EndpointServiceName)
		assert.Equal(t, int32(100), spec.VMAccountID)
		assert.Equal(t, int32(200), spec.VMProjectID)
		assert.Equal(t, "100m", spec.VMAlertCPURequest)
		assert.Equal(t, "200m", spec.VMAlertCPULimit)
		assert.Equal(t, "128Mi", spec.VMAlertMemoryRequest)
		assert.Equal(t, "256Mi", spec.VMAlertMemoryLimit)

		// Verify status fields
		assert.Equal(t, k8sCluster.Name, status.ClusterID)
		assert.Equal(t, string(constants.ACTIVE), status.Phase)
		assert.Equal(t, "test-cluster.example.com", status.DNSName)
	})

	t.Run("handles deletion timestamp", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}
		k8sCluster := createTestCluster()
		deletionTime := metav1.Now()
		k8sCluster.DeletionTimestamp = &deletionTime

		cluster, _, _, err := c.convertK8sToCluster(k8sCluster, false)

		assert.NoError(t, err)
		assert.NotNil(t, cluster.DeletionTimestamp)
		assert.Equal(t, deletionTime.Time, *cluster.DeletionTimestamp)
	})

	t.Run("returns error for invalid type", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}
		invalidObj := &corev1.Pod{}

		_, _, _, err := c.convertK8sToCluster(invalidObj, false)

		assert.ErrorIs(t, err, ErrTypeInvalid)
	})
}

func TestConvertClusterToK8s(t *testing.T) {
	t.Run("successfully converts database records to K8s cluster", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		now := time.Now()
		cluster := &Cluster{
			ClusterID:         "test-cluster",
			Namespace:         "default",
			Region:            "us-west-2",
			Tenant:            "tenant-1",
			ProjectID:         "project-1",
			ApplicationID:     "app-1",
			BizType:           "dedicated",
			CreationTimestamp: now,
			UpdateTimestamp:   now,
			Spec: ClusterSpec{
				ClusterID:              "test-cluster",
				Labels:                 map[string]string{"key": "value"},
				Annotations:            map[string]string{"anno": "value"},
				EndpointServiceName:    "test-endpoint",
				EndpointServiceUserARN: "arn:aws:iam::123456789012:user/test",
				EndpointServiceShared:  false,
				MuteAlert:              false,
				VMAccountID:            100,
				VMProjectID:            200,
				VMSupportServerless:    true,
				VMClusterName:          "vm-cluster-1",
				VMAvailabilityZone:     "us-west-2a",
				VMAlertCPURequest:      "100m",
				VMAlertCPULimit:        "200m",
				VMAlertMemoryRequest:   "128Mi",
				VMAlertMemoryLimit:     "256Mi",
			},
			Status: ClusterStatus{
				ClusterID:       "test-cluster",
				Phase:           string(constants.ACTIVE),
				DNSName:         "test-cluster.example.com",
				UpdateAt:        "2024-01-01T00:00:00Z",
				ResourceVersion: 1,
			},
		}

		obj := &v1.Cluster{}
		err := c.convertClusterToK8s(cluster, obj)

		assert.NoError(t, err)
		assert.Equal(t, "test-cluster", obj.Name)
		assert.Equal(t, "default", obj.Namespace)
		assert.Equal(t, "1", obj.ResourceVersion)
		assert.Equal(t, "test-endpoint", obj.Spec.Endpoint.Name)
		assert.Equal(t, int32(100), obj.Spec.VictoriaAccount.AccountID)
		assert.Equal(t, constants.ACTIVE, obj.Status.Phase)
	})

	t.Run("handles deletion timestamp", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		now := time.Now()
		deletionTime := now.Add(1 * time.Hour)
		cluster := &Cluster{
			ClusterID:         "test-cluster",
			Namespace:         "default",
			CreationTimestamp: now,
			DeletionTimestamp: &deletionTime,
			Spec: ClusterSpec{
				ClusterID: "test-cluster",
			},
			Status: ClusterStatus{
				ClusterID:       "test-cluster",
				ResourceVersion: 1,
			},
		}

		obj := &v1.Cluster{}
		err := c.convertClusterToK8s(cluster, obj)

		assert.NoError(t, err)
		assert.NotNil(t, obj.DeletionTimestamp)
		assert.Equal(t, deletionTime, obj.DeletionTimestamp.Time)
	})
}

func TestPaginationToken(t *testing.T) {
	t.Run("encode and decode continue token", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		cursor := &paginationCursor{
			LastClusterID: "cluster-123",
		}

		token, err := c.encodeContinueToken(cursor)
		assert.NoError(t, err)
		assert.NotEmpty(t, token)

		decodedCursor, err := c.decodeContinueToken(token)
		assert.NoError(t, err)
		assert.Equal(t, cursor.LastClusterID, decodedCursor.LastClusterID)
	})

	t.Run("returns empty token for nil cursor", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		token, err := c.encodeContinueToken(nil)
		assert.NoError(t, err)
		assert.Empty(t, token)
	})

	t.Run("returns error for invalid token", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		_, err := c.decodeContinueToken("invalid-token")
		assert.Error(t, err)
	})

	t.Run("returns error for empty token", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		_, err := c.decodeContinueToken("")
		assert.Error(t, err)
	})
}

func TestGenerateContinueToken(t *testing.T) {
	t.Run("generates token when more results exist", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		clusters := []Cluster{
			{ClusterID: "cluster-1"},
			{ClusterID: "cluster-2"},
			{ClusterID: "cluster-3"},
		}

		token, err := c.generateContinueToken(clusters, 2)
		assert.NoError(t, err)
		assert.NotEmpty(t, token)
	})

	t.Run("returns empty token when no more results", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		clusters := []Cluster{
			{ClusterID: "cluster-1"},
			{ClusterID: "cluster-2"},
		}

		token, err := c.generateContinueToken(clusters, 2)
		assert.NoError(t, err)
		assert.Empty(t, token)
	})

	t.Run("returns empty token when limit is 0", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		clusters := []Cluster{
			{ClusterID: "cluster-1"},
		}

		token, err := c.generateContinueToken(clusters, 0)
		assert.NoError(t, err)
		assert.Empty(t, token)
	})
}

func TestGetIndexedFieldForLabel(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	tests := []struct {
		labelKey      string
		expectedField string
	}{
		{constants.LabelClusterID, "clusters.cluster_id"},
		{constants.LabelTenantID, "clusters.tenant"},
		{constants.LabelProjectID, "clusters.project_id"},
		{constants.LabelApplicationID, "clusters.application_id"},
		{constants.LabelBizType, "clusters.biz_type"},
		{"custom-label", ""},
	}

	for _, tt := range tests {
		t.Run(tt.labelKey, func(t *testing.T) {
			field := c.getIndexedFieldForLabel(tt.labelKey)
			assert.Equal(t, tt.expectedField, field)
		})
	}
}

func TestBuildResourceRequirements(t *testing.T) {
	t.Run("builds resource requirements with all fields", func(t *testing.T) {
		resources := buildResourceRequirements("100m", "200m", "128Mi", "256Mi")

		assert.Equal(t, "100m", resources.Requests.Cpu().String())
		assert.Equal(t, "128Mi", resources.Requests.Memory().String())
		assert.Equal(t, "200m", resources.Limits.Cpu().String())
		assert.Equal(t, "256Mi", resources.Limits.Memory().String())
	})

	t.Run("handles empty strings", func(t *testing.T) {
		resources := buildResourceRequirements("", "", "", "")

		assert.Empty(t, resources.Requests)
		assert.Empty(t, resources.Limits)
	})

	t.Run("handles invalid quantities", func(t *testing.T) {
		resources := buildResourceRequirements("invalid", "invalid", "invalid", "invalid")

		assert.Empty(t, resources.Requests)
		assert.Empty(t, resources.Limits)
	})
}

func TestCheckObject(t *testing.T) {
	t.Run("valid object", func(t *testing.T) {
		obj := &v1.Cluster{}
		err := checkObject(obj)
		assert.NoError(t, err)
	})

	t.Run("non-pointer object", func(t *testing.T) {
		obj := v1.Cluster{}
		err := checkObject(&obj)
		assert.NoError(t, err)
	})

	t.Run("nil pointer", func(t *testing.T) {
		var obj *v1.Cluster
		err := checkObject(obj)
		assert.ErrorIs(t, err, ErrValueInvalid)
	})
}

func TestLogger(t *testing.T) {
	t.Run("returns logger with request ID when present in context", func(t *testing.T) {
		baseLogger := logr.Discard()
		c := &mysqlClient{
			log: baseLogger,
		}

		requestID := "test-request-id-123"
		ctx := context.WithValue(context.Background(), constants.OpenAPIHeaderRequestId, requestID)

		logger := c.logger(ctx)

		// The logger should have the request_id value added
		// We can't directly inspect logr.Logger values, but we can verify it doesn't panic
		assert.NotNil(t, logger)
	})

	t.Run("returns base logger when request ID not in context", func(t *testing.T) {
		baseLogger := logr.Discard()
		c := &mysqlClient{
			log: baseLogger,
		}

		ctx := context.Background()
		logger := c.logger(ctx)

		assert.NotNil(t, logger)
	})

	t.Run("returns base logger when request ID is wrong type", func(t *testing.T) {
		baseLogger := logr.Discard()
		c := &mysqlClient{
			log: baseLogger,
		}

		// Set a non-string value for the request ID
		ctx := context.WithValue(context.Background(), constants.OpenAPIHeaderRequestId, 12345)
		logger := c.logger(ctx)

		assert.NotNil(t, logger)
	})
}

func TestGroupVersionKindFor(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("returns GVK for valid object", func(t *testing.T) {
		cluster := createTestCluster()
		gvk, err := c.GroupVersionKindFor(cluster)

		assert.NoError(t, err)
		assert.Equal(t, "observability.pingcap.com/v1", gvk.GroupVersion().String())
		assert.Equal(t, "Cluster", gvk.Kind)
	})

	t.Run("returns error for nil object", func(t *testing.T) {
		_, err := c.GroupVersionKindFor(nil)
		assert.Error(t, err)
	})
}

func TestIsObjectNamespaced(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("returns true for cluster object", func(t *testing.T) {
		cluster := createTestCluster()
		namespaced, err := c.IsObjectNamespaced(cluster)

		assert.NoError(t, err)
		assert.True(t, namespaced)
	})

	t.Run("returns error for nil object", func(t *testing.T) {
		_, err := c.IsObjectNamespaced(nil)
		assert.Error(t, err)
	})
}

func TestSubResource(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("returns status sub-resource client", func(t *testing.T) {
		subResource := c.SubResource("status")
		assert.NotNil(t, subResource)
	})

	t.Run("returns nil for unknown sub-resource", func(t *testing.T) {
		subResource := c.SubResource("unknown")
		assert.Nil(t, subResource)
	})
}

// Additional tests for better coverage

func TestApplyLabelSelector(t *testing.T) {
	sqlDB, _, gormDB := setupMockDB(t)
	defer sqlDB.Close()

	c := &mysqlClient{db: gormDB, componentName: "test"}

	t.Run("applies indexed field requirement with In operator", func(t *testing.T) {
		req, _ := labels.NewRequirement(constants.LabelTenantID, selection.In, []string{"tenant-1", "tenant-2"})
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies indexed field requirement with NotIn operator", func(t *testing.T) {
		req, _ := labels.NewRequirement(constants.LabelTenantID, selection.NotIn, []string{"tenant-1"})
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies indexed field requirement with Exists operator", func(t *testing.T) {
		req, _ := labels.NewRequirement(constants.LabelProjectID, selection.Exists, nil)
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies indexed field requirement with DoesNotExist operator", func(t *testing.T) {
		req, _ := labels.NewRequirement(constants.LabelApplicationID, selection.DoesNotExist, nil)
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies JSON field requirement for custom labels", func(t *testing.T) {
		req, _ := labels.NewRequirement("custom-label", selection.In, []string{"value1"})
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies JSON field requirement with NotIn operator", func(t *testing.T) {
		req, _ := labels.NewRequirement("custom-label", selection.NotIn, []string{"value1"})
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies JSON field requirement with Exists operator", func(t *testing.T) {
		req, _ := labels.NewRequirement("custom-label", selection.Exists, nil)
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})

	t.Run("applies JSON field requirement with DoesNotExist operator", func(t *testing.T) {
		req, _ := labels.NewRequirement("custom-label", selection.DoesNotExist, nil)
		selector := labels.NewSelector().Add(*req)

		query := c.db.Model(&Cluster{})
		query = c.applyLabelSelector(query, selector)

		assert.NotNil(t, query)
	})
}

func TestListWithPagination(t *testing.T) {
	t.Run("lists with continue token", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		// Create a valid continue token
		cursor := &paginationCursor{LastClusterID: "cluster-1"}
		token, _ := c.encodeContinueToken(cursor)

		mock.ExpectQuery("SELECT .* FROM `clusters` WHERE clusters.cluster_id > \\?").
			WithArgs("cluster-1").
			WillReturnRows(sqlmock.NewRows([]string{"cluster_id"}))

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list, &client.ListOptions{Continue: token})

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error for invalid continue token", func(t *testing.T) {
		_, _, gormDB := setupMockDB(t)
		c := &mysqlClient{db: gormDB, componentName: "test"}

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list, &client.ListOptions{Continue: "invalid-token"})

		assert.Error(t, err)
	})

	t.Run("generates continue token when more results exist", func(t *testing.T) {
		c := &mysqlClient{db: nil, componentName: "test"}

		clusters := []Cluster{
			{ClusterID: "cluster-1"},
			{ClusterID: "cluster-2"},
			{ClusterID: "cluster-3"},
		}

		token, err := c.generateContinueToken(clusters, 2)
		assert.NoError(t, err)
		assert.NotEmpty(t, token)

		// Verify we can decode it
		cursor, err := c.decodeContinueToken(token)
		assert.NoError(t, err)
		assert.Equal(t, "cluster-2", cursor.LastClusterID)
	})
}

func TestDeleteWithAlreadyDeletedTimestamp(t *testing.T) {
	t.Run("skips delete when deletion timestamp already set", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		deletionTime := time.Now()

		mock.ExpectBegin()

		// Mock get cluster with deletion timestamp already set
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, deletionTime)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		// Mock get status for version - GORM adds LIMIT clause
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectCommit()

		err := c.Delete(context.Background(), cluster)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error when force delete without deletion timestamp", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		// Mock get cluster without deletion timestamp
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, nil)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		// Mock get status for version - GORM adds LIMIT clause
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster, WithForce(func() {}))

		assert.ErrorIs(t, err, ErrDeleteCond)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns conflict error on version mismatch during delete", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, nil)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))

		// Mock resource version update with 0 rows affected (conflict)
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 0))

		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster)

		assert.True(t, apierrors.IsConflict(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestConvertK8sToClusterWithOptionalFields(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("converts with max queue size", func(t *testing.T) {
		cluster := createTestCluster()
		maxQueueSize := int32(1000)
		cluster.Spec.VictoriaAccount.MaxQueueSize = &maxQueueSize

		_, spec, _, err := c.convertK8sToCluster(cluster, false)

		assert.NoError(t, err)
		assert.Equal(t, int32(1000), spec.VMAlertMaxQueueSize)
	})

	t.Run("converts with rule selector", func(t *testing.T) {
		cluster := createTestCluster()
		ruleSelector := metav1.LabelSelector{
			MatchLabels: map[string]string{"env": "prod"},
		}
		cluster.Spec.VictoriaAccount.RuleSelector = &ruleSelector

		_, spec, _, err := c.convertK8sToCluster(cluster, false)

		assert.NoError(t, err)
		assert.Equal(t, ruleSelector, spec.VMRuleSelector)
	})

	t.Run("converts with alertmanagers", func(t *testing.T) {
		cluster := createTestCluster()
		alertmanagers := []prometheusv1.AlertmanagerEndpoints{
			{
				Namespace: "monitoring",
				Name:      "alertmanager",
				Port:      intstr.FromString("web"),
			},
		}
		cluster.Spec.VictoriaAccount.Alerting = &prometheusv1.AlertingSpec{
			Alertmanagers: alertmanagers,
		}

		_, spec, _, err := c.convertK8sToCluster(cluster, false)

		assert.NoError(t, err)
		assert.Equal(t, alertmanagers, spec.VMAlertManagers)
	})

	t.Run("converts with partial resource requirements", func(t *testing.T) {
		cluster := createTestCluster()
		cluster.Spec.VictoriaAccount.AlertResources = corev1.ResourceRequirements{
			Requests: corev1.ResourceList{
				corev1.ResourceCPU: resource.MustParse("100m"),
			},
		}

		_, spec, _, err := c.convertK8sToCluster(cluster, false)

		assert.NoError(t, err)
		assert.Equal(t, "100m", spec.VMAlertCPURequest)
		// When memory is not set, it returns "0" (zero quantity string)
		assert.Equal(t, "0", spec.VMAlertMemoryRequest)
	})

	t.Run("converts with empty resource requirements", func(t *testing.T) {
		cluster := createTestCluster()
		cluster.Spec.VictoriaAccount.AlertResources = corev1.ResourceRequirements{}

		_, spec, _, err := c.convertK8sToCluster(cluster, false)

		assert.NoError(t, err)
		assert.Empty(t, spec.VMAlertCPURequest)
		assert.Empty(t, spec.VMAlertCPULimit)
		assert.Empty(t, spec.VMAlertMemoryRequest)
		assert.Empty(t, spec.VMAlertMemoryLimit)
	})
}

func TestConvertClusterToK8sWithOptionalFields(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("converts with max queue size", func(t *testing.T) {
		now := time.Now()
		cluster := &Cluster{
			ClusterID:         "test-cluster",
			Namespace:         "default",
			CreationTimestamp: now,
			Spec: ClusterSpec{
				ClusterID:           "test-cluster",
				VMAlertMaxQueueSize: 1000,
			},
			Status: ClusterStatus{
				ClusterID:       "test-cluster",
				ResourceVersion: 1,
			},
		}

		obj := &v1.Cluster{}
		err := c.convertClusterToK8s(cluster, obj)

		assert.NoError(t, err)
		assert.NotNil(t, obj.Spec.VictoriaAccount.MaxQueueSize)
		assert.Equal(t, int32(1000), *obj.Spec.VictoriaAccount.MaxQueueSize)
	})

	t.Run("converts with alertmanagers", func(t *testing.T) {
		now := time.Now()
		alertmanagers := []prometheusv1.AlertmanagerEndpoints{
			{
				Namespace: "monitoring",
				Name:      "alertmanager",
				Port:      intstr.FromString("web"),
			},
		}
		alertmanagersJSON, _ := json.Marshal(alertmanagers)

		cluster := &Cluster{
			ClusterID:         "test-cluster",
			Namespace:         "default",
			CreationTimestamp: now,
			Spec: ClusterSpec{
				ClusterID:       "test-cluster",
				VMAlertManagers: alertmanagers,
			},
			Status: ClusterStatus{
				ClusterID:       "test-cluster",
				ResourceVersion: 1,
			},
		}

		// Unmarshal to ensure proper serialization
		var parsedAlertmanagers []prometheusv1.AlertmanagerEndpoints
		json.Unmarshal(alertmanagersJSON, &parsedAlertmanagers)

		obj := &v1.Cluster{}
		err := c.convertClusterToK8s(cluster, obj)

		assert.NoError(t, err)
		assert.NotNil(t, obj.Spec.VictoriaAccount.Alerting)
		assert.Len(t, obj.Spec.VictoriaAccount.Alerting.Alertmanagers, 1)
	})

	t.Run("converts without optional fields", func(t *testing.T) {
		now := time.Now()
		cluster := &Cluster{
			ClusterID:         "test-cluster",
			Namespace:         "default",
			CreationTimestamp: now,
			Spec: ClusterSpec{
				ClusterID:           "test-cluster",
				VMAlertMaxQueueSize: 0,
				VMAlertManagers:     []prometheusv1.AlertmanagerEndpoints{},
			},
			Status: ClusterStatus{
				ClusterID:       "test-cluster",
				ResourceVersion: 1,
			},
		}

		obj := &v1.Cluster{}
		err := c.convertClusterToK8s(cluster, obj)

		assert.NoError(t, err)
		assert.Nil(t, obj.Spec.VictoriaAccount.MaxQueueSize)
		assert.Nil(t, obj.Spec.VictoriaAccount.Alerting)
	})
}

func TestPatchWithDifferentTypes(t *testing.T) {
	t.Run("patches with JSON patch type", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		// Mock Get operation
		mock.ExpectBegin()
		now := time.Now()
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "region", "biz_type", "tenant", "project_id", "application_id",
			"creation_timestamp", "update_timestamp", "deletion_timestamp",
		}).AddRow(
			cluster.Name, "default", "us-west-2", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		)
		mock.ExpectQuery("SELECT .* FROM `clusters`").WillReturnRows(clusterRows)

		labelsJSON, _ := json.Marshal(map[string]string{"key": "value"})
		annotationsJSON, _ := json.Marshal(map[string]string{"anno": "value"})
		specRows := sqlmock.NewRows([]string{
			"cluster_id", "labels", "annotations",
			"endpoint_service_name", "endpoint_service_user_arn", "endpoint_service_shared",
			"mute_alert", "vm_account_id", "vm_project_id", "vm_support_serverless",
			"vm_cluster_name", "vm_availability_zone", "vm_rule_selector",
			"vm_alert_cpu_request", "vm_alert_cpu_limit", "vm_alert_memory_request", "vm_alert_memory_limit",
			"vm_alert_managers", "vmalert_max_queue_size", "creation_timestamp", "update_timestamp",
		}).AddRow(
			cluster.Name, labelsJSON, annotationsJSON,
			"endpoint", "arn", false,
			false, 100, 200, true,
			"vm-cluster", "us-west-2a", "{}",
			"100m", "200m", "128Mi", "256Mi",
			"[]", 0, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_specs`").WillReturnRows(specRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "phase", "dns_name", "update_at", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(
			cluster.Name, "Running", "test.example.com", "2024-01-01", 1, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").WillReturnRows(statusRows)
		mock.ExpectCommit()

		// Mock Update operation
		mock.ExpectBegin()
		statusRows2 := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").WillReturnRows(statusRows2)
		mock.ExpectExec("UPDATE `clusters`").WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_specs`").WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_statuses`").WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("INSERT INTO `cluster_events`").WillReturnResult(sqlmock.NewResult(1, 1))
		mock.ExpectCommit()

		patchData := []byte(`{"spec":{"muteAlert":true}}`)
		patch := client.RawPatch(types.JSONPatchType, patchData)

		err := c.Patch(context.Background(), cluster, patch)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error for unsupported patch type", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		// Mock Get operation
		mock.ExpectBegin()
		now := time.Now()
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "region", "biz_type", "tenant", "project_id", "application_id",
			"creation_timestamp", "update_timestamp", "deletion_timestamp",
		}).AddRow(
			cluster.Name, "default", "us-west-2", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		)
		mock.ExpectQuery("SELECT .* FROM `clusters`").WillReturnRows(clusterRows)

		labelsJSON, _ := json.Marshal(map[string]string{"key": "value"})
		annotationsJSON, _ := json.Marshal(map[string]string{"anno": "value"})
		specRows := sqlmock.NewRows([]string{
			"cluster_id", "labels", "annotations",
			"endpoint_service_name", "endpoint_service_user_arn", "endpoint_service_shared",
			"mute_alert", "vm_account_id", "vm_project_id", "vm_support_serverless",
			"vm_cluster_name", "vm_availability_zone", "vm_rule_selector",
			"vm_alert_cpu_request", "vm_alert_cpu_limit", "vm_alert_memory_request", "vm_alert_memory_limit",
			"vm_alert_managers", "vmalert_max_queue_size", "creation_timestamp", "update_timestamp",
		}).AddRow(
			cluster.Name, labelsJSON, annotationsJSON,
			"endpoint", "arn", false,
			false, 100, 200, true,
			"vm-cluster", "us-west-2a", "{}",
			"100m", "200m", "128Mi", "256Mi",
			"[]", 0, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_specs`").WillReturnRows(specRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "phase", "dns_name", "update_at", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(
			cluster.Name, "Running", "test.example.com", "2024-01-01", 1, now, now,
		)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").WillReturnRows(statusRows)
		mock.ExpectCommit()

		// Use an unsupported patch type
		patchData := []byte(`{"spec":{"muteAlert":true}}`)
		patch := client.RawPatch(types.ApplyPatchType, patchData)

		err := c.Patch(context.Background(), cluster, patch)

		assert.Error(t, err)
		assert.Contains(t, err.Error(), "unsupported patch type")
	})
}

func TestJSONMergePatch(t *testing.T) {
	t.Run("merges JSON successfully", func(t *testing.T) {
		original := []byte(`{"name":"test","value":1}`)
		patch := []byte(`{"value":2,"new":"field"}`)

		merged, err := jsonMergePatch(original, patch)

		assert.NoError(t, err)

		var result map[string]interface{}
		json.Unmarshal(merged, &result)

		assert.Equal(t, "test", result["name"])
		assert.Equal(t, float64(2), result["value"])
		assert.Equal(t, "field", result["new"])
	})

	t.Run("removes fields with null values", func(t *testing.T) {
		original := []byte(`{"name":"test","value":1}`)
		patch := []byte(`{"value":null}`)

		merged, err := jsonMergePatch(original, patch)

		assert.NoError(t, err)

		var result map[string]interface{}
		json.Unmarshal(merged, &result)

		assert.Equal(t, "test", result["name"])
		_, exists := result["value"]
		assert.False(t, exists)
	})

	t.Run("returns error for invalid original JSON", func(t *testing.T) {
		original := []byte(`invalid json`)
		patch := []byte(`{"value":2}`)

		_, err := jsonMergePatch(original, patch)

		assert.Error(t, err)
	})

	t.Run("returns error for invalid patch JSON", func(t *testing.T) {
		original := []byte(`{"name":"test"}`)
		patch := []byte(`invalid json`)

		_, err := jsonMergePatch(original, patch)

		assert.Error(t, err)
	})
}

func TestStatusWriterCreate(t *testing.T) {
	t.Run("create calls update", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectCommit()

		statusWriter := c.Status()
		err := statusWriter.Create(context.Background(), cluster, cluster)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestSubResourceClient(t *testing.T) {
	sqlDB, mock, gormDB := setupMockDB(t)
	defer sqlDB.Close()

	c := &mysqlClient{db: gormDB, componentName: "test"}
	subResourceClient := c.SubResource("status")

	t.Run("Get returns not implemented error", func(t *testing.T) {
		cluster := createTestCluster()
		err := subResourceClient.Get(context.Background(), cluster, cluster)

		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not implemented")
	})

	t.Run("Create delegates to writer", func(t *testing.T) {
		cluster := createTestCluster()

		mock.ExpectBegin()
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectCommit()

		err := subResourceClient.Create(context.Background(), cluster, cluster)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("Update delegates to writer", func(t *testing.T) {
		cluster := createTestCluster()

		mock.ExpectBegin()
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectCommit()

		err := subResourceClient.Update(context.Background(), cluster)

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestWithTx(t *testing.T) {
	t.Run("commits transaction on success", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectBegin()
		mock.ExpectCommit()

		err := c.withTx(context.Background(), func(tx *gorm.DB) error {
			return nil
		})

		assert.NoError(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("rolls back transaction on error", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectBegin()
		mock.ExpectRollback()

		err := c.withTx(context.Background(), func(tx *gorm.DB) error {
			return sql.ErrConnDone
		})

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("handles panic and rolls back", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectBegin()
		mock.ExpectRollback()

		err := c.withTx(context.Background(), func(tx *gorm.DB) error {
			panic("test panic")
		})

		assert.Error(t, err)
		assert.Contains(t, err.Error(), "panic in transaction")
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestBuildResourceRequirementsPartial(t *testing.T) {
	t.Run("builds with only CPU request", func(t *testing.T) {
		resources := buildResourceRequirements("100m", "", "", "")

		assert.Equal(t, "100m", resources.Requests.Cpu().String())
		assert.True(t, resources.Requests.Memory().IsZero())
		assert.True(t, resources.Limits.Cpu().IsZero())
		assert.True(t, resources.Limits.Memory().IsZero())
	})

	t.Run("builds with only memory limit", func(t *testing.T) {
		resources := buildResourceRequirements("", "", "", "256Mi")

		assert.True(t, resources.Requests.Cpu().IsZero())
		assert.True(t, resources.Requests.Memory().IsZero())
		assert.True(t, resources.Limits.Cpu().IsZero())
		assert.Equal(t, "256Mi", resources.Limits.Memory().String())
	})

	t.Run("handles mixed valid and invalid quantities", func(t *testing.T) {
		resources := buildResourceRequirements("100m", "invalid", "128Mi", "invalid")

		assert.Equal(t, "100m", resources.Requests.Cpu().String())
		assert.Equal(t, "128Mi", resources.Requests.Memory().String())
		assert.True(t, resources.Limits.Cpu().IsZero())
		assert.True(t, resources.Limits.Memory().IsZero())
	})
}

func TestPaginationCursorValidation(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("returns error for cursor with empty cluster ID", func(t *testing.T) {
		cursor := &paginationCursor{LastClusterID: ""}
		token, err := c.encodeContinueToken(cursor)
		require.NoError(t, err)

		_, err = c.decodeContinueToken(token)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "missing last_cluster_id")
	})
}

func TestNewMySQLClientWithDefaultTTL(t *testing.T) {
	t.Run("uses default TTL when not specified", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		mock.ExpectPing()

		// Reset global DB for test
		mu.Lock()
		globalDB = nil
		mu.Unlock()

		client := &mysqlClient{
			db:            gormDB,
			componentName: "test-component",
			eventTTL:      0,
		}

		// When eventTTL is 0, NewMySQLClient sets it to DefaultEventTTL
		if client.eventTTL == 0 {
			client.eventTTL = DefaultEventTTL
		}

		assert.Equal(t, DefaultEventTTL, client.eventTTL)
	})
}

func TestSchemeAndRESTMapper(t *testing.T) {
	c := &mysqlClient{componentName: "test"}

	t.Run("Scheme panics", func(t *testing.T) {
		assert.Panics(t, func() {
			c.Scheme()
		})
	})

	t.Run("RESTMapper panics", func(t *testing.T) {
		assert.Panics(t, func() {
			c.RESTMapper()
		})
	})

	t.Run("DeleteAllOf panics", func(t *testing.T) {
		assert.Panics(t, func() {
			c.DeleteAllOf(context.Background(), &v1.Cluster{})
		})
	})
}

func TestStatusWriterPatch(t *testing.T) {
	c := &mysqlClient{componentName: "test"}
	statusWriter := c.Status()

	t.Run("Patch panics", func(t *testing.T) {
		cluster := createTestCluster()
		patch := client.RawPatch(types.MergePatchType, []byte(`{}`))

		assert.Panics(t, func() {
			statusWriter.Patch(context.Background(), cluster, patch)
		})
	})
}

func TestSubResourceClientPatch(t *testing.T) {
	c := &mysqlClient{componentName: "test"}
	subResourceClient := c.SubResource("status")

	t.Run("Patch panics", func(t *testing.T) {
		cluster := createTestCluster()
		patch := client.RawPatch(types.MergePatchType, []byte(`{}`))

		assert.Panics(t, func() {
			subResourceClient.Patch(context.Background(), cluster, patch)
		})
	})
}

func TestGetWithDatabaseError(t *testing.T) {
	t.Run("returns error on database failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectBegin()
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		obj := &v1.Cluster{}
		err := c.Get(context.Background(), client.ObjectKey{Name: "test-cluster"}, obj)

		assert.Error(t, err)
		assert.False(t, apierrors.IsNotFound(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestCreateWithDatabaseError(t *testing.T) {
	t.Run("returns error on insert failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()
		mock.ExpectQuery("SELECT count\\(\\*\\) FROM `clusters`").
			WithArgs(cluster.Name).
			WillReturnRows(sqlmock.NewRows([]string{"count(*)"}).AddRow(0))
		mock.ExpectExec("INSERT INTO `clusters`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Create(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on event insert failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()
		mock.ExpectQuery("SELECT count\\(\\*\\) FROM `clusters`").
			WithArgs(cluster.Name).
			WillReturnRows(sqlmock.NewRows([]string{"count(*)"}).AddRow(0))
		mock.ExpectExec("INSERT INTO `clusters`").
			WillReturnResult(sqlmock.NewResult(1, 1))
		mock.ExpectExec("INSERT INTO `cluster_specs`").
			WillReturnResult(sqlmock.NewResult(1, 1))
		mock.ExpectExec("INSERT INTO `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(1, 1))
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Create(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestUpdateWithDatabaseErrors(t *testing.T) {
	t.Run("returns error on cluster update failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()
		cluster.ResourceVersion = "1"

		mock.ExpectBegin()

		now := time.Now()
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Update(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on spec update failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()
		cluster.ResourceVersion = "1"

		mock.ExpectBegin()

		now := time.Now()
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_specs`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Update(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on status update failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()
		cluster.ResourceVersion = "1"

		mock.ExpectBegin()

		now := time.Now()
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_specs`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Update(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on event insert failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()
		cluster.ResourceVersion = "1"

		mock.ExpectBegin()

		now := time.Now()
		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version", "creation_timestamp", "update_timestamp",
		}).AddRow(cluster.Name, 1, now, now)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_specs`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Update(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestDeleteWithDatabaseErrors(t *testing.T) {
	t.Run("returns error on status query failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, nil)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on soft delete failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, nil)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on event insert failure during soft delete", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()

		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, nil)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("UPDATE `clusters`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("UPDATE `cluster_statuses`").
			WillReturnResult(sqlmock.NewResult(0, 1))
		mock.ExpectExec("INSERT INTO `cluster_events`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on hard delete failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test", eventTTL: 10 * time.Minute}
		cluster := createTestCluster()
		deletionTime := metav1.Now()
		cluster.DeletionTimestamp = &deletionTime

		mock.ExpectBegin()

		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "deletion_timestamp",
		}).AddRow(cluster.Name, cluster.Namespace, deletionTime.Time)
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(clusterRows)

		statusRows := sqlmock.NewRows([]string{
			"cluster_id", "resource_version",
		}).AddRow(cluster.Name, 1)
		mock.ExpectQuery("SELECT .* FROM `cluster_statuses`").
			WithArgs(cluster.Name, 1).
			WillReturnRows(statusRows)

		mock.ExpectExec("DELETE FROM `clusters`").
			WillReturnError(sql.ErrConnDone)
		mock.ExpectRollback()

		err := c.Delete(context.Background(), cluster, WithForce(func() {}))

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestListWithErrors(t *testing.T) {
	t.Run("returns error on query failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnError(sql.ErrConnDone)

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list)

		assert.Error(t, err)
		assert.NoError(t, mock.ExpectationsWereMet())
	})

	t.Run("returns error on conversion failure", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}

		now := time.Now()
		clusterRows := sqlmock.NewRows([]string{
			"cluster_id", "namespace", "region", "biz_type", "tenant", "project_id", "application_id",
			"creation_timestamp", "update_timestamp", "deletion_timestamp",
		}).AddRow(
			"cluster-1", "default", "us-west-2", "dedicated", "tenant-1", "project-1", "app-1",
			now, now, nil,
		)

		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnRows(clusterRows)

		// Mock spec query to return error
		mock.ExpectQuery("SELECT .* FROM `cluster_specs`").
			WillReturnError(sql.ErrConnDone)

		list := &v1.ClusterList{}
		err := c.List(context.Background(), list)

		assert.Error(t, err)
	})
}

func TestStatusWriterWithInvalidType(t *testing.T) {
	t.Run("returns error for non-cluster object", func(t *testing.T) {
		_, _, gormDB := setupMockDB(t)
		c := &mysqlClient{db: gormDB, componentName: "test"}

		statusWriter := c.Status()
		invalidObj := &corev1.Pod{}

		err := statusWriter.Update(context.Background(), invalidObj)

		assert.ErrorIs(t, err, ErrTypeInvalid)
	})
}

func TestConvertClusterListToK8sWithError(t *testing.T) {
	t.Run("returns error for invalid list type", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		clusters := []Cluster{
			{ClusterID: "test-cluster"},
		}

		invalidList := &corev1.PodList{}
		err := c.convertClusterListToK8s(clusters, invalidList)

		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not a ClusterList type")
	})
}

func TestConvertClusterToK8sWithError(t *testing.T) {
	t.Run("returns error for invalid object type", func(t *testing.T) {
		c := &mysqlClient{componentName: "test"}

		now := time.Now()
		cluster := &Cluster{
			ClusterID:         "test-cluster",
			Namespace:         "default",
			CreationTimestamp: now,
			Spec: ClusterSpec{
				ClusterID: "test-cluster",
			},
			Status: ClusterStatus{
				ClusterID:       "test-cluster",
				ResourceVersion: 1,
			},
		}

		invalidObj := &corev1.Pod{}
		err := c.convertClusterToK8s(cluster, invalidObj)

		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not a Cluster type")
	})
}

func TestPatchWithGetError(t *testing.T) {
	t.Run("returns error when Get fails", func(t *testing.T) {
		sqlDB, mock, gormDB := setupMockDB(t)
		defer sqlDB.Close()

		c := &mysqlClient{db: gormDB, componentName: "test"}
		cluster := createTestCluster()

		mock.ExpectBegin()
		mock.ExpectQuery("SELECT .* FROM `clusters`").
			WillReturnError(gorm.ErrRecordNotFound)
		mock.ExpectRollback()

		patchData := []byte(`{"spec":{"muteAlert":true}}`)
		patch := client.RawPatch(types.MergePatchType, patchData)

		err := c.Patch(context.Background(), cluster, patch)

		assert.Error(t, err)
		assert.True(t, apierrors.IsNotFound(err))
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}

func TestApplyIndexedFieldRequirementWithEquals(t *testing.T) {
	sqlDB, _, gormDB := setupMockDB(t)
	defer sqlDB.Close()

	c := &mysqlClient{db: gormDB, componentName: "test"}

	t.Run("applies Equals operator", func(t *testing.T) {
		req, _ := labels.NewRequirement(constants.LabelTenantID, selection.Equals, []string{"tenant-1"})

		query := c.db.Model(&Cluster{})
		query = c.applyIndexedFieldRequirement(query, "clusters.tenant", *req)

		assert.NotNil(t, query)
	})

	t.Run("applies NotEquals operator", func(t *testing.T) {
		req, _ := labels.NewRequirement(constants.LabelTenantID, selection.NotEquals, []string{"tenant-1"})

		query := c.db.Model(&Cluster{})
		query = c.applyIndexedFieldRequirement(query, "clusters.tenant", *req)

		assert.NotNil(t, query)
	})
}

func TestApplyJSONFieldRequirementWithEquals(t *testing.T) {
	sqlDB, _, gormDB := setupMockDB(t)
	defer sqlDB.Close()

	c := &mysqlClient{db: gormDB, componentName: "test"}

	t.Run("applies Equals operator for JSON field", func(t *testing.T) {
		req, _ := labels.NewRequirement("custom-label", selection.Equals, []string{"value1"})

		query := c.db.Model(&Cluster{})
		query = c.applyJSONFieldRequirement(query, "custom-label", *req)

		assert.NotNil(t, query)
	})

	t.Run("applies NotEquals operator for JSON field", func(t *testing.T) {
		req, _ := labels.NewRequirement("custom-label", selection.NotEquals, []string{"value1"})

		query := c.db.Model(&Cluster{})
		query = c.applyJSONFieldRequirement(query, "custom-label", *req)

		assert.NotNil(t, query)
	})
}
