package grpc

import (
	"context"
	goerr "errors"
	"fmt"
	"testing"

	"github.com/go-sql-driver/mysql"
	"github.com/pingcap/errors"
	"github.com/stretchr/testify/require"
)

func TestSQLPayloadErrorMessage(t *testing.T) {
	tests := map[string]struct {
		err      error
		expected string
	}{
		"nil error": {
			err:      nil,
			expected: "",
		},
		"mysql error": {
			err:      &mysql.MySQLError{Number: 1064, Message: "You have an error in your SQL syntax"},
			expected: "Error 1064: You have an error in your SQL syntax",
		},
		"wrapped mysql error": {
			err:      errors.Trace(&mysql.MySQLError{Number: 1146, Message: "Table 'test.missing' doesn't exist"}),
			expected: "Error 1146: Table 'test.missing' doesn't exist",
		},
		"non sql error": {
			err:      goerr.New("connection reset by peer"),
			expected: "",
		},
	}

	for name, tc := range tests {
		t.Run(name, func(t *testing.T) {
			require.Equal(t, tc.expected, sqlPayloadErrorMessage(tc.err))
		})
	}
}

func TestSourceDBPayloadErrorMessage(t *testing.T) {
	tests := map[string]struct {
		err      error
		expected string
	}{
		"nil error": {
			err:      nil,
			expected: "",
		},
		"mysql error": {
			err:      &mysql.MySQLError{Number: 1045, Message: "Access denied for user 'root'@'%'"},
			expected: "Error 1045: Access denied for user 'root'@'%'",
		},
		"source network timeout": {
			err:      goerr.New("dial tcp 10.0.74.125:3306: i/o timeout"),
			expected: "dial tcp 10.0.74.125:3306: i/o timeout",
		},
		"source connection refused": {
			err:      errors.Trace(goerr.New("dial tcp 127.0.0.1:3306: connect: connection refused")),
			expected: "dial tcp 127.0.0.1:3306: connect: connection refused",
		},
		"context canceled": {
			err:      context.Canceled,
			expected: "",
		},
		"context deadline exceeded": {
			err:      context.DeadlineExceeded,
			expected: "",
		},
		"source timeout wrapping context deadline": {
			err:      fmt.Errorf("dial tcp 10.0.74.125:3306: i/o timeout: %w", context.DeadlineExceeded),
			expected: "dial tcp 10.0.74.125:3306: i/o timeout: context deadline exceeded",
		},
		"non source db error": {
			err:      goerr.New("request failed"),
			expected: "",
		},
	}

	for name, tc := range tests {
		t.Run(name, func(t *testing.T) {
			require.Equal(t, tc.expected, sourceDBPayloadErrorMessage(tc.err))
		})
	}
}
