package client

import (
	"context"
	"database/sql"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/stretchr/testify/assert"
	v1 "github.com/tidbcloud/observability/api/regionalserver/resourceworker/v1"
	"github.com/tidbcloud/observability/pkg/common/constants"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestStatusWriterUpdate(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 := &v1.Cluster{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "test-cluster",
				Namespace: "default",
			},
			Status: v1.ClusterStatus{
				Phase:       constants.ACTIVE,
				DnsName:     "test.example.com",
				ServiceName: "test-service",
				UpdateAt:    "2024-01-01T00:00:00Z",
			},
		}

		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())
	})

	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"}
		cluster := &v1.Cluster{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "test-cluster",
				Namespace: "default",
			},
			Status: v1.ClusterStatus{
				Phase: constants.ACTIVE,
			},
		}

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

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

		assert.Error(t, err)
		assert.Contains(t, err.Error(), "failed to update cluster status")
		assert.NoError(t, mock.ExpectationsWereMet())
	})
}
