package common

import (
	"database/sql"
	"fmt"
	"time"

	l4g "github.com/alecthomas/log4go"
	"github.com/avast/retry-go"
	"github.com/dailymotion/allure-go"
	"github.com/tidbcloud/qa-PlatformAPIAuto/common"
	"github.com/tidbcloud/qa-PlatformAPIAuto/models"
)

func (s *SceneTest) GetServerlessTiDBConnection() (*sql.DB, error) {
	pathParam := map[string]string{
		"org_id":     s.DbaasRequestInfo.CommonEnv.OrgId,
		"project_id": s.DbaasRequestInfo.CommonEnv.ProjectId,
		"cluster_id": s.ServerlessClusterId,
	}
	callResp := s.DbaasRequestInfo.DbassRequest(s.T, "getClusterInfo", nil, pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		errorMsg := fmt.Errorf("status code is: %d, http details is: %s", httpInfo.RespStatusCode, httpInfo.ToString())
		l4g.Error(errorMsg)
		allure.FailNow(errorMsg)
	}

	clusterResp := &models.CentralGetClusterResp{}
	httpInfo.UnmarshalRespBody(clusterResp)

	tidbAddress := clusterResp.Cluster.Endpoint.Address
	tidbPort := clusterResp.Cluster.Endpoint.Port
	token := *clusterResp.Cluster.Endpoint.Token

	return common.ConnectServerlessUseTLS(*tidbAddress, (int64)(*tidbPort), s.Password, "test", token+".root")
}

func (s *SceneTest) ExecuteServerlessTidbDataStep(dataFunc MySQLStatement) {
	allure.Step(
		allure.Description("execute serverless tidb data step"),
		allure.Action(func() {
			db, err := s.GetServerlessTiDBConnection()
			defer db.Close()
			if err != nil {
				errorMsg := fmt.Errorf("connect to serverless tidb occur error: %s", err)
				l4g.Error(errorMsg)
				allure.FailNow(errorMsg)
			}

			err = dataFunc(db)
			if err != nil {
				errorMsg := fmt.Errorf("init serverless tidb data occur error: %s", err)
				l4g.Error(errorMsg)
				allure.FailNow(errorMsg)
			}
		}),
	)
}

func (s *SceneTest) ExecuteServerlessDataWithRetryStep(checkFunc MySQLStatement) {
	allure.Step(
		allure.Description("check Serverless TiDB data step"),
		allure.Action(func() {
			db, err := s.GetServerlessTiDBConnection()
			defer db.Close()
			if err != nil {
				errorMsg := fmt.Errorf("connect Serverless TiDB occur error: %s", err)
				l4g.Error(errorMsg)
				allure.FailNow(errorMsg)
			}
			err = retry.Do(
				func() error {
					return checkFunc(db)
				},
				retry.DelayType(retry.FixedDelay),
				retry.Delay(time.Second*10),
				retry.Attempts(6),
				retry.OnRetry(func(n uint, err error) {
					l4g.Info("#%d: %s\n", n, err)
				}),
			)

			if err != nil {
				l4g.Error(err)
				allure.FailNow(err)
			}
		}),
	)
}
