package instancemetering

import (
	"context"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/metering/pkg/common/models"
)

func TestDatabase_ClusterMeta(t *testing.T) {
	db, err := GetClusterMetaDB(fmt.Sprintf("%s/%s", testDataPath, "123123.sqlite"))
	assert.NoError(t, err)

	clusterMetas := []models.ClusterMeta{
		{
			TenantID:     "111",
			ProjectID:    "222",
			ClusterID:    "333",
			Cluster:      "aaa",
			DevTier:      false,
			Poc:          true,
			CrossAccount: false,
			Provider:     "aws",
			Region:       "us-west-2",
			Components: []*models.ComponentMeta{
				{
					ComponentType: "pd",
					Count:         3,
				},
				{
					ComponentType: "tikv",
					Count:         5,
				},

				{
					ComponentType: "tidb",
					Count:         2,
				},
			},
			Timestamp: 123123,
		},
		{
			TenantID:     "111",
			ProjectID:    "444",
			ClusterID:    "555",
			Cluster:      "bbb",
			DevTier:      false,
			Poc:          true,
			CrossAccount: false,
			Provider:     "aws",
			Region:       "us-west-2",
			Components: []*models.ComponentMeta{
				{
					ComponentType: "pd",
					Count:         3,
				},
				{
					ComponentType: "tikv",
					Count:         5,
				},

				{
					ComponentType: "tidb",
					Count:         1,
				},
			},
			Timestamp: 123123,
		},
		{
			TenantID:     "6666",
			ProjectID:    "7777",
			ClusterID:    "8888",
			Cluster:      "cccc",
			DevTier:      false,
			Poc:          true,
			CrossAccount: false,
			Provider:     "azure",
			Region:       "eastus",
			Components: []*models.ComponentMeta{
				{
					ComponentType: "pd",
					Count:         4,
				},
				{
					ComponentType: "tikv",
					Count:         7,
				},

				{
					ComponentType: "tidb",
					Count:         5,
				},
			},
			Timestamp: 123123,
		},
	}
	err = db.SaveClusterMeta(context.TODO(), clusterMetas)
	assert.NoError(t, err)

	result, err := db.ListClusterMeta(context.TODO())
	assert.NoError(t, err)
	assert.Equal(t, 3, len(result))
}

func TestDatabase_ClusterMeta_Error(t *testing.T) {
	_, err := GetClusterMetaDB("/$%^(/tttt/tttt.sqlite")
	assert.Error(t, err)
}

func TestDatabase_BillingReports(t *testing.T) {
	db, err := GetBillingReportDB(fmt.Sprintf("%s/%s", testDataPath, "456456.sqlite"))
	assert.NoError(t, err)

	billings := []*models.BillingReport{
		{
			TenantID:      111,
			CostID:        "ewqerwqr",
			Cost:          55555,
			CostTimestamp: 456456,
			Labels:        "{}",
			Unit:          "node:tidb",
		},
		{
			TenantID:      222,
			CostID:        "fdsfafsdg",
			Cost:          2,
			CostTimestamp: 456456,
			Labels:        "{}",
			Unit:          "node:pd",
		},
	}
	err = db.SaveBillingReports(context.TODO(), billings)
	assert.NoError(t, err)

	result, err := db.ListBillingReports(context.TODO())
	assert.NoError(t, err)
	assert.Equal(t, 2, len(result))
	assert.Equal(t, int64(456456), result[0].CostTimestamp)
}

func TestGetBillingReportDB(t *testing.T) {
	db, err := GetBillingReportDB(fmt.Sprintf("%s/%s", testDataPath, "billing.sqlite"))
	assert.NoError(t, err)
	assert.NotEmpty(t, db.base)

	assert.True(t, db.base.Migrator().HasTable(models.BillingReport{}))
	assert.False(t, db.base.Migrator().HasTable(models.ClusterMeta{}))
}

func TestGetBillingReportDB_Error(t *testing.T) {
	_, err := GetBillingReportDB("/$%^(/tttt/tttt.sqlite")
	assert.Error(t, err)
}

func TestGetClusterMetaDB(t *testing.T) {
	db, err := GetClusterMetaDB(fmt.Sprintf("%s/%s", testDataPath, "meta.sqlite"))
	assert.NoError(t, err)
	assert.NotEmpty(t, db.base)

	assert.True(t, db.base.Migrator().HasTable(models.ClusterMeta{}))
	assert.True(t, db.base.Migrator().HasTable(models.ComponentMeta{}))
	assert.False(t, db.base.Migrator().HasTable(models.BillingReport{}))
}
