package tests

import (
	"testing"
	"time"

	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/model/billing"
	"github.com/pingcap/dbaas/billing2/model/costexplorer"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/shopspring/decimal"
	"github.com/stretchr/testify/suite"
)

type UsageExplorerSuite struct {
	tests.BillingTestSuite
}

func TestUsageExplorerSuite(t *testing.T) {
	suite.Run(t, new(UsageExplorerSuite))

}

func (suite *UsageExplorerSuite) TestCostExplorerInternal() {
	assert := suite.Assert()

	var billingDate = time.Date(2021, 11, 1, 0, 0, 0, 0, time.UTC)
	measureModel := &billing.MeasureModel{}
	const tenantID uint = 1
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)

	var appid uint64 = 1234

	err := datainit.CreatePaymentMock(tenantID)
	assert.NoError(err)
	_, err = (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   costexplorer.DataAPIRequestCount,
		Category:  "category_A",
		Price:     decimal.NewFromInt(0),
		SkuType:   entity.SkuType_Test,
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)

	_, err = (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   costexplorer.DataAPINetWorkCount,
		Category:  "category_B",
		Price:     decimal.NewFromInt(0),
		SkuType:   entity.SkuType_Test,
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)

	_, err = (&billing.BindedPackageModel{}).BindPackage(tenantID, 1)
	assert.NoError(err)

	unitCosts1 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          costexplorer.DataAPIRequestCount,
		Cost:          5,
		Labels:        map[string]string{costexplorer.MeasureLabelKeyAppId: "1234"},
	}
	unitCosts2 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          costexplorer.DataAPINetWorkCount,
		Cost:          5,

		Labels: map[string]string{costexplorer.MeasureLabelKeyAppId: "1234"},
	}
	unitCosts3 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          costexplorer.DataAPINetWorkCount,
		Internal:      true,
		Cost:          5,
		Labels:        map[string]string{costexplorer.MeasureLabelKeyAppId: "12345"},
	}

	config.Get().Set(config.DataapiUsageUnitsMap, map[string]string{costexplorer.DataAPIRequestCount: costexplorer.DataAPIRequestCount,
		costexplorer.DataAPINetWorkCount: costexplorer.DataAPINetWorkCount})

	var allCosts []entity.UserUnitCost

	_, err = measureModel.CostUnits(tenantID, &unitCosts1)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts2)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts3)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts1)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts2)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts3)
	assert.NoError(err)
	err = entity.NewUserUnitCostQuerySet(db.GetDB()).All(&allCosts)

	usageExplorerModel := &costexplorer.UsageExplorerModel{}
	res, err := usageExplorerModel.GetMonthlyAppUsage(tenantID, &forms.CostExplorerQuery{
		StartDate: billingDate,
		EndDate:   billingDate.Add(time.Hour),
		Units:     []string{costexplorer.DataAPINetWorkCount, costexplorer.DataAPIRequestCount},
	}, appid, "")

	assert.Equal(res.RequestCount, int64(10))
	assert.Equal(res.NetworkUsage, int64(10))

	//pp.Print(res.DataAPIUsageExplore)
}

func (suite *UsageExplorerSuite) TestCostExplorerForAPPInternal() {
	assert := suite.Assert()

	var billingDate = time.Date(2021, 11, 1, 0, 0, 0, 0, time.UTC)
	measureModel := &billing.MeasureModel{}
	const tenantID uint = 1
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)

	var appid uint64 = 1234

	err := datainit.CreatePaymentMock(tenantID)
	assert.NoError(err)
	_, err = (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   costexplorer.DataAPIRequestCount,
		Category:  "category_A",
		Price:     decimal.NewFromInt(0),
		SkuType:   entity.SkuType_Test,
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)

	_, err = (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   costexplorer.DataAPINetWorkCount,
		Category:  "category_B",
		Price:     decimal.NewFromInt(0),
		SkuType:   entity.SkuType_Test,
		PriceType: entity.PriceType_Normal,
	})

	assert.NoError(err)
	_, err = (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   "token-1",
		Category:  "category_A",
		Price:     decimal.NewFromInt(0),
		SkuType:   entity.SkuType_Test,
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)
	_, err = (&billing.BindedPackageModel{}).BindPackage(tenantID, 1)
	assert.NoError(err)

	unitCosts1 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          costexplorer.DataAPIRequestCount,
		Cost:          5,
		Labels:        map[string]string{costexplorer.MeasureLabelKeyAppId: "1234"},
	}
	unitCosts2 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          costexplorer.DataAPINetWorkCount,
		Cost:          5,

		Labels: map[string]string{costexplorer.MeasureLabelKeyAppId: "1234"},
	}
	unitCosts3 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          "token-1",
		Internal:      true,
		Cost:          5,
		Labels:        map[string]string{costexplorer.MeasureLabelKeyAppId: "1234"},
	}

	config.Get().Set("eda"+costexplorer.AppCfgSuffix, map[string]string{costexplorer.DataAPIRequestCount: costexplorer.DataAPIRequestCount,
		costexplorer.DataAPINetWorkCount: costexplorer.DataAPINetWorkCount, "token-1": "token"})

	var allCosts []entity.UserUnitCost

	_, err = measureModel.CostUnits(tenantID, &unitCosts1)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts2)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts3)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts1)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts2)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts3)
	assert.NoError(err)
	err = entity.NewUserUnitCostQuerySet(db.GetDB()).All(&allCosts)
	usageExplorerModel := &costexplorer.UsageExplorerModel{}

	res, err := usageExplorerModel.GetMonthlyAppUsage(tenantID, &forms.CostExplorerQuery{
		StartDate: billingDate,
		EndDate:   billingDate.Add(time.Hour),
		Units:     []string{costexplorer.DataAPINetWorkCount, costexplorer.DataAPIRequestCount, "token-1"},
	}, appid, "eda")

	assert.Equal(res.RequestCount, int64(0))
	assert.Equal(res.NetworkUsage, int64(0))
	assert.Equal(res.UsageMap["token"], int64(10))
	assert.Equal(res.UsageMap["request"], int64(10))
	assert.Equal(res.UsageMap["network"], int64(10))

	//pp.Print(res)
}
