package bss

import (
	"fmt"

	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/qa-PlatformAPIAuto/common"
	"github.com/tidbcloud/qa-gourd/ProductService"
	"github.com/tidbcloud/qa-gourd/util"
)

func RunBillingTest(w *ProductService.WebRequestInfo, UrlInfoMap map[string]ProductService.UrlInfo, reporter *util.AllureReporter) {
	bt := &BillingTest{}
	bt.Init(w, UrlInfoMap, reporter)
	bt.CheckBillingCoreAPI()
}

func (bt *BillingTest) CheckBillingCoreAPI() {
	// check tenant plan
	bt.Reporter.StepReport("A-CheckTenantPlan", func() {
		bt.CheckTenantPlan(bt.SetOrgTenantPlan())
	})

	// check tenant's credits
	bt.Reporter.StepReport("B-CheckTenantCredits", func() {
		bt.CheckCredits(bt.SetOrgTenantCredits(), bt.SetOrgTenantCreditsSummary())
	})

	// check tenant's Payments
	bt.Reporter.StepReport("C-CheckTenantPayments", func() {
		bt.CheckPayments(bt.OrgTenantPlan, bt.SetOrgTenantPayment())
	})
}

func (bt *BillingTest) CheckTenantPlan(TenantPlan *common.TenantPlanInfo, expectPlan ...string) {
	bt.Reporter.StepReport(fmt.Sprintf("Check Tenant Plan, Effective Plan is : %s , Ondemand Plan status is : %s , PoC Plan status is : %s , test expect plan is : %s .",
		TenantPlan.EffectivePlan,
		TenantPlan.OnDemandPlanInfo.Status,
		TenantPlan.POCPlanInfo.Status,
		expectPlan,
	), func() {
		if TenantPlan.EffectivePlan == "on_demand" {
			if TenantPlan.OnDemandPlanInfo.Status != "active" {
				assert.Fail(bt.Reporter.T, "Tenant's effective plan is on_demand, however on_demand plan info is not active !")
			}
		} else if TenantPlan.EffectivePlan == "poc" {
			if TenantPlan.POCPlanInfo.Status != "active" && TenantPlan.POCPlanInfo.Status != "closing" && TenantPlan.POCPlanInfo.Status != "closed" {
				assert.Fail(bt.Reporter.T, "Tenant's effective plan is poc , however poc plan info is not active/closing/closed !")
			}
		} else if TenantPlan.EffectivePlan == "free_trial" {
			if TenantPlan.POCPlanInfo.Status == "active" || TenantPlan.OnDemandPlanInfo.Status == "active" {
				assert.Fail(bt.Reporter.T, "Tenant's effective plan is free_trial , however poc/on_demand plan info is active !")
			}
		} else {
			assert.Fail(bt.Reporter.T, fmt.Sprintf("Tenant's effective plan [%s] is invalid !", TenantPlan.EffectivePlan))
		}
		for _, plan := range expectPlan {
			if TenantPlan.EffectivePlan != plan {
				assert.Fail(bt.Reporter.T, fmt.Sprintf("Tenant's effective plan [%s] is not equal to expected plan [%s] !", TenantPlan.EffectivePlan, plan))
			}
		}
	})
}

// check tenant's credits detail scene
func (bt *BillingTest) CheckCredits(CreditsList *common.Credits, CreditsSummary *common.CreditsSummary) {
	// check :  total credits of credits summary = sum(all credits)
	sum_credits := common.SumCredits(CreditsList)
	bt.Reporter.StepReport(fmt.Sprintf("Check total credits of CreditsSummary [ %s ] = sum of all credits [ %s ] . ",
		CreditsSummary.TotalCredits,
		sum_credits,
	), func() {
		assert.Equal(bt.Reporter.T, CreditsSummary.TotalCredits, sum_credits)
	})
	// check : current usage of credits summary = sum (credits) - sum (remaining)
	sum_remaining := common.SumRemainingCredits(CreditsList)
	Usage := CreditsSummary.TotalCostedCredits
	bt.Reporter.StepReport(fmt.Sprintf("Check current usage of CreditsSummary  [%s]  =  sum (credits) [%s] - sum (remaining) [%s] .  ",
		Usage,
		sum_credits,
		sum_remaining,
	), func() {
		assert.Equal(bt.Reporter.T, true, Usage.Equal(sum_credits.Sub(sum_remaining)))
	})
	//check : available credits of credits summary = sum (valid remaining)
	sum_valid_remaining := common.SumValidRemainingCredits(CreditsList)
	bt.Reporter.StepReport(fmt.Sprintf("Check available remaining credits of CreditsSummary [ %s ] = sum of valid remaining credits [ %s ] . ",
		CreditsSummary.AvailableRemainingCredits,
		sum_valid_remaining,
	), func() {
		assert.Equal(bt.Reporter.T, true, CreditsSummary.AvailableRemainingCredits.Equal(sum_valid_remaining))
	})
}

func (bt *BillingTest) CheckPayments(tenantPlan string, payment *common.PaymentMethod) {
	result := true
	if tenantPlan != "on_demand" {
		if payment.Payable {
			result = false
		}
	} else {
		if !payment.Payable || payment.Status != "active" {
			result = false
		}
	}

	bt.Reporter.StepReport(fmt.Sprintf("Check tenantPlan is [%s], payment is [%+v] . ",
		tenantPlan,
		payment,
	), func() {
		assert.Equal(bt.Reporter.T, true, result)
	})
}
