package bss

import (
	"fmt"
	"net/http"
	"time"

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

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

// This case can not run in parallel since we have to switch token a lot.
func (bt *BillingTest) CheckCreditsScene() {
	// get pre tenant plan
	// free-trial - do all test
	// poc - doesn't do case D,G
	// ondemand - doesn't do case D,G
	bt.Reporter.StepReport("A-CheckCurrentTenantPlan", func() {
		bt.CheckTenantPlan(bt.SetOrgTenantPlan())
		bt.SetbtTestUserEnv(bt.w.User.TenantEmail, bt.w.User.OrgId, bt.w.User.ProjectId)
	})
	// add credits
	var CreditsPackageId int
	prePlan := bt.OrgTenantPlan
	bt.Reporter.StepReport("B-AddCredits", func() {
		CreditsPackageId = bt.CheckOPSAddCredits()
		if prePlan != PlanOnDemand {
			util.SecondTimeWait(30, 10, "Wait For Tenant Plan Sync")
			bt.CheckTenantPlan(bt.SetOrgTenantPlan(), PlanPoC)
		}
	})

	// dbaas get credits
	bt.Reporter.StepReport("C-CheckDBaaSCredits", func() {
		bt.CheckCredits(bt.SetOrgTenantCredits(), bt.SetOrgTenantCreditsSummary())
	})

	// dbaas create&delete dedicated cluster
	if prePlan == PlanFreeTrial {
		bt.Reporter.StepReport("D-CanCreateDedicatedCluster", func() {
			bt.CheckCreateDedicatedInSpecEnv(true)
		})
	}
	// reclaim credits
	bt.Reporter.StepReport("E-ReclaimCredits", func() {
		bt.CheckOPSReclaimCredits(CreditsPackageId)
	})
	// dbaas get credits
	bt.Reporter.StepReport("F-CheckDBaaSCredits", func() {
		bt.CheckCredits(bt.SetOrgTenantCredits(), bt.SetOrgTenantCreditsSummary())
	})

	// dbaas can not create dedicated cluster
	if prePlan == PlanFreeTrial {
		bt.Reporter.StepReport("G-CanNOTCreateDedicatedCluster", func() {
			bt.CheckCreateDedicatedInSpecEnv(false)
		})
	}
}

// return credits package id
func (bt *BillingTest) CheckOPSAddCredits(addCreditBodys ...*common.AddCredits) int {
	pathParam := map[string]string{
		"org_id": bt.w.User.OrgId,
	}
	startTime := time.Now().UTC().AddDate(0, 0, -1).Format("2006-01-02T15:04:05Z")
	EndTime := time.Now().UTC().AddDate(0, 0, 1).Format("2006-01-02T15:04:05Z")
	addCreditBody := common.NewAddCredits(startTime, EndTime)
	for _, Body := range addCreditBodys {
		addCreditBody = Body
	}
	bt.w.ResetRequestEmail(handler.OtherUserInfo.OpsAdminEmail)
	addCreditsResp := bt.w.DoWebAPIRequestByUrlInfo(bt.URLInfoMap["addCredits"], addCreditBody, pathParam, nil)
	bt.w.ResetRequestEmail(bt.btUserEmail)
	bt.Reporter.StepReport(fmt.Sprintf("addCredits's status code is %s, response is : %v",
		addCreditsResp.Raw().Status,
		addCreditsResp.Body().Raw(),
	), func() {
		addCreditsResp.Status(http.StatusOK)
	})

	CreditsPackageId := int(addCreditsResp.JSON().Path("$.credits_package_id").Number().Raw())

	bt.Reporter.StepReport(fmt.Sprintf("addCredits's package id is : %d",
		CreditsPackageId,
	), func() {
		assert.NotEmpty(bt.Reporter.T, CreditsPackageId)
	})

	return CreditsPackageId
}

func (bt *BillingTest) CheckOPSReclaimCredits(CreditsPackageId int) {
	if CreditsPackageId == 0 {
		bt.Reporter.StepReport(fmt.Sprintf("reclaimCredits's package id is : %d",
			CreditsPackageId,
		), func() {
			assert.Fail(bt.Reporter.T, "CreditsPackageId is 0")
		})
	}

	pathParam := map[string]string{
		"org_id":     bt.w.User.OrgId,
		"package_id": fmt.Sprintf("%d", CreditsPackageId),
	}
	bt.w.ResetRequestEmail(handler.OtherUserInfo.OpsAdminEmail)
	reclaimCreditsResp := bt.w.DoWebAPIRequestByUrlInfo(bt.URLInfoMap["reclaimCredits"], nil, pathParam, nil)
	bt.w.ResetRequestEmail(bt.btUserEmail)
	bt.Reporter.StepReport(fmt.Sprintf("reclaimCredits's status code is %s, response is : %v",
		reclaimCreditsResp.Raw().Status,
		reclaimCreditsResp.Body().Raw(),
	), func() {
		reclaimCreditsResp.Status(http.StatusOK)
	})
}
