package baseresp

import (
	"context"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/serverless-service/idl/pbgen/proto/console"
	"github.com/tidbcloud/serverless-service/internal/errorcode"
	"google.golang.org/grpc"
)

type testClusterSQLError struct {
	bizerr.BizError
	errno uint16
	msg   string
}

func (e *testClusterSQLError) Error() string {
	return fmt.Sprintf("SQL error %d: %s", e.errno, e.msg)
}

func (e *testClusterSQLError) ClusterSQLError() (uint16, string) {
	return e.errno, e.msg
}

func TestUnaryServerInterceptorFormatsWrappedBusinessError(t *testing.T) {
	interceptor := UnaryServerInterceptor()
	want := bizerr.New(bizerr.ErrCodeParams, "invalid input")

	got, err := interceptor(
		context.Background(),
		nil,
		&grpc.UnaryServerInfo{},
		func(context.Context, any) (any, error) {
			return &console.EmptyResp{}, fmt.Errorf("wrapped: %w", want)
		},
	)

	require.NoError(t, err)
	resp := got.(*console.EmptyResp)
	assert.Equal(t, int64(want.ErrCode()), resp.BaseResp.ErrCode)
	assert.Equal(t, "invalid input", resp.BaseResp.ErrMsg)
}

func TestUnaryServerInterceptorFormatsClusterSQLError(t *testing.T) {
	interceptor := UnaryServerInterceptor()

	got, err := interceptor(
		context.Background(),
		nil,
		&grpc.UnaryServerInfo{},
		func(context.Context, any) (any, error) {
			sqlErr := &testClusterSQLError{
				BizError: bizerr.New(errorcode.ErrCodeSvcClusterProxy, "cluster SQL error"),
				errno:    1146,
				msg:      "Table 'private.orders' doesn't exist",
			}
			return &console.EmptyResp{}, errorcode.MarkClusterSQLErrorUserActionable(sqlErr)
		},
	)

	require.NoError(t, err)
	resp := got.(*console.EmptyResp)
	assert.Equal(t, int64(errorcode.ErrCodeClusterSQLError), resp.BaseResp.ErrCode)
	assert.Equal(t, "The requested table does not exist. (error 1146)", resp.BaseResp.ErrMsg)
	assert.NotContains(t, resp.BaseResp.ErrMsg, "private.orders")
}
