package tests

import (
	"testing"

	"github.com/pingcap/dbaas/billing2/constant"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/handler/centralhandler"
	"github.com/pingcap/dbaas/billing2/handler/paymenthandler"
	"github.com/pingcap/dbaas/billing2/handler/paymenthandler/impl"
	"github.com/pingcap/dbaas/billing2/model/payment/paymentsub"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/pingcap/dbaas/billing2/utils/timeutils"

	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/shopspring/decimal"
	"github.com/stretchr/testify/suite"
)

type AwsReconciliationTestTestSuit struct {
	tests.BillingTestSuite
}

func TestAwsReconciliationTestTestSuit(t *testing.T) {
	suite.Run(t, new(AwsReconciliationTestTestSuit))
}

func (s *AwsReconciliationTestTestSuit) TestParse() {
	assert := s.Assert()
	config.Get().Set(config.AWSProductCode, "3v813oc4b1fot1zqe0zzyrkny")
	err := (&entity.PaymentMethod{
		PaymentType: entity.PaymentType_AWS,
		PaymentCode: "Wb3ABoJhAHA",
	}).Create(db.GetDB())
	assert.NoError(err)
	awsHandler := &impl.AwsPaymentHandlerImpl{}
	result, err := awsHandler.ParseAWSReport([]byte(TestAWSInput))
	assert.NoError(err)
	assert.Len(result, 18)
	cnt := 0
	for _, res := range result {
		if res.PaymentCode == "Wb3ABoJhAHA" {
			assert.Equal(decimal.RequireFromString("32.59"), res.Revenue)
			cnt++
		}
	}
	assert.Equal(1, cnt)
}

type MockCentralHandlerImpl struct {
	centralhandler.CentralHandler
}

func (*MockCentralHandlerImpl) GetTenant(tenantID uint) (*forms.Tenant, error) {
	return &forms.Tenant{
		TenantID:                  tenantID,
		ThirdPartyAccountCode:     "rasdcsa",
		ThirdPartyAccountProvider: constant.AwsAccountProvider,
		Status:                    centralhandler.TenantStatusActive,
	}, nil
}

func (*MockCentralHandlerImpl) GetProjectInfo(projectID uint) (*forms.Project, error) {
	return &forms.Project{
		ID:   projectID,
		Name: "project",
	}, nil
}

func (s *AwsReconciliationTestTestSuit) TestChannelLoss() {
	centralhandler.SetCentralHandler(&MockCentralHandlerImpl{})
	assert := s.Assert()
	config.Get().Set(config.AWSProductCode, "3v813oc4b1fot1zqe0zzyrkny")
	config.Get().Set(config.EnableAWSProduct1DollarUnit, true)
	config.Get().Set(config.AWSPaymentEnable, false)
	paymenthandler.SetPaymentHandler(&impl.PaymentHandlerImpl{})
	tenantID := uint(1)
	billingConfigID := uint(1)
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	invoices := []forms.Invoice{
		{
			InvoiceID: 1,
			StartDate: timeutils.GetNow(),
			Costs: forms.Costs{
				CategoryCosts: forms.CategoryCosts{
					Price: forms.Price{
						CostPrice: decimal.RequireFromString("32.77"),
					},
				},
			},
		},
		{
			InvoiceID: 2,
			StartDate: timeutils.GetNow(),
			Costs: forms.Costs{
				CategoryCosts: forms.CategoryCosts{
					Price: forms.Price{
						CostPrice: decimal.RequireFromString("3.2"),
					},
				},
			},
		},
	}
	payment, err := (&paymentsub.PaymentModel{}).CreatePaymentMethodAndActive(
		tenantID,
		&forms.PaymentMethodCreateQuery{
			PaymentType:           entity.PaymentType_AWS,
			BindedBillingConfigID: &billingConfigID,
		},
	)
	assert.NoError(err)
	assert.NoError(err)
	handler := &impl.AwsPaymentHandlerImpl{}
	result, err := handler.PayMultiInvoice(payment, nil, invoices)
	assert.NoError(err)
	assert.Len(result, 2)
	assert.Equal(decimal.RequireFromString("0.77"), result[0].ChannelLoss)
	assert.Equal(decimal.RequireFromString("0.2"), result[1].ChannelLoss)

	payment.PaymentMeta = forms.PaymentMeta{EnlargeMarketplaceMetering: true, EnlargerDiscount: decimal.RequireFromString("0.66")}
	result, err = handler.PayMultiInvoice(payment, nil, invoices)
	assert.NoError(err)
	assert.Len(result, 2)
	assert.Equal(decimal.RequireFromString("32.77").Sub(decimal.RequireFromString("32.77").Div(payment.PaymentMeta.EnlargerDiscount).Truncate(0).Mul(payment.PaymentMeta.EnlargerDiscount)), result[0].ChannelLoss)
	assert.Equal(decimal.RequireFromString("3.2").Sub(decimal.RequireFromString("3.2").Div(payment.PaymentMeta.EnlargerDiscount).Truncate(0).Mul(payment.PaymentMeta.EnlargerDiscount)), result[1].ChannelLoss)
}
