package dm

import (
	"testing"

	"github.com/pingcap/errors"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/dataflow-service/internal/config"
	"github.com/tidbcloud/dataflow-service/internal/db/entity"
)

func TestSupportedSources(t *testing.T) {
	sources := SupportedSources("other")
	require.Len(t, sources, 0)

	sources = SupportedSources("aws")
	require.Len(t, sources, 3)
	require.Equal(t, string(entity.DBTypeMySQL), sources[0].Name)
	require.Len(t, sources[0].ConnMethods, 3)
	require.Equal(t, string(entity.DBTypeAWSAuroraMySQL), sources[1].Name)
	require.Len(t, sources[1].ConnMethods, 3)
	require.Equal(t, string(entity.DBTypeAWSRDSMySQL), sources[2].Name)
	require.Len(t, sources[2].ConnMethods, 3)
	// require.Equal(t, string(entity.DBTypeGoogleCloudMySQL), sources[3].Name)
	// require.Len(t, sources[3].ConnMethods, 1)

	sources = SupportedSources("gcp")
	require.Len(t, sources, 4)
	require.Equal(t, string(entity.DBTypeMySQL), sources[0].Name)
	require.Len(t, sources[0].ConnMethods, 2)
	require.Equal(t, string(entity.DBTypeAWSAuroraMySQL), sources[1].Name)
	require.Len(t, sources[1].ConnMethods, 1)
	require.Equal(t, string(entity.DBTypeAWSRDSMySQL), sources[2].Name)
	require.Len(t, sources[2].ConnMethods, 1)
	require.Equal(t, string(entity.DBTypeGoogleCloudMySQL), sources[3].Name)
	require.Len(t, sources[3].ConnMethods, 2)
}

func TestUnpackSourceID(t *testing.T) {
	_, err := UnpackSourceID("sou")
	require.Error(t, err)
	_, err = UnpackSourceID("source-")
	require.Error(t, err)
	_, err = UnpackSourceID("source-xxx")
	require.Error(t, err)
	id, err := UnpackSourceID("source-123")
	require.NoError(t, err)
	require.Equal(t, uint64(123), id)
}

func TestNormalizeErr(t *testing.T) {
	err := NormalizeErr(errors.New("Error 1045: Access denied for user 'root'@'xxx' (using password: YES)"), "annotate")
	require.Contains(t, err.Error(), "Access denied for the input user to connect the database")

	err = NormalizeErr(errors.New("dial tcp: lookup xxx on 172.20.0.10:53: no such host"), "annotate")
	require.Contains(t, err.Error(), "Failed to connect to the database using given host and port")

	err = NormalizeErr(errors.New("dial tcp 23.22.22.33:3306: i/o timeout"), "annotate")
	require.Contains(t, err.Error(), "Failed to connect to the database using given host and port")

	err = NormalizeErr(errors.New("denied for user 'root'@'xxx' (using password: YES)"), "annotate")
	require.Contains(t, err.Error(), "annotate")
}

func TestIgnoreDB(t *testing.T) {
	testCases := []struct {
		db       string
		expected bool
	}{
		{"information_schema", true},
		{"mysql", true},
		{"performance_schema", true},
		{"sys", true},
		{"abc", false},
	}
	for _, tc := range testCases {
		require.Equal(t, tc.expected, IsMysqlSystemDB(tc.db))
	}
}

func TestGetNodeSKU(t *testing.T) {
	require.NoError(t, config.MockConfig())
	t.Cleanup(func() {
		// reset config
		require.NoError(t, config.MockConfig())
	})
	require.Nil(t, config.Global().DMConfig.RCUPriceMap)

	// invalid cloud provider
	_, err := GetNodeRCUPrice("xxx", "us-west-2")
	require.Error(t, err)

	config.Global().DMConfig.RCUPriceMap = map[string]map[string]float64{
		"aws": {
			"us-west-2": 0.1307,
			"sa-east-1": 0.2035,
		},
		"gcp": {
			"us-west1": 0.1452,
		},
	}
	// invalid region
	_, err = GetNodeRCUPrice("aws", "us-west-222222")
	require.Error(t, err)

	sku, err := GetNodeRCUPrice("aws", "us-west-2")
	require.NoError(t, err)
	require.Equal(t, 0.1307, sku)
	sku, err = GetNodeRCUPrice("aws", "sa-east-1")
	require.NoError(t, err)
	require.Equal(t, 0.2035, sku)

	sku, err = GetNodeRCUPrice("gcp", "us-west1")
	require.NoError(t, err)
	require.Equal(t, 0.1452, sku)
}
