package common

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

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

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

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

func (s *SceneTest) ExecuteMySQLDataWithRetryStep(checkFunc MySQLStatement) {
	allure.Step(
		allure.Description("check MySQL data step"),
		allure.Action(func() {
			db, err := s.GetMySQLConnection()
			defer db.Close()
			if err != nil {
				errorMsg := fmt.Errorf("connect MySQL 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)
			}
		}),
	)
}

func (s *SceneTest) GetMySQLConnection() (*sql.DB, error) {
	slice := strings.Split(s.DbaasRequestInfo.CommonEnv.MysqlUrl, ":")
	address := slice[0]
	port, err := strconv.ParseInt(slice[1], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("parse MySQL port occur error: %s", err)
	}
	return common.ConnectTidb(address, port, s.DbaasRequestInfo.CommonEnv.MysqlPassword, "test", s.DbaasRequestInfo.CommonEnv.MysqlUser)
}

func (s *SceneTest) InitMySQL(db *sql.DB) error {
	return DropSchema(db, s.TestSchemaName)
}

func (s *SceneTest) CheckFullStageTableCount(db *sql.DB) error {
	err := CheckMySQLTableCount(db, s.TestSchemaName, string(TABLE_TEST1), 1)
	if err != nil {
		return err
	}
	err = CheckMySQLTableCount(db, s.TestSchemaName, string(TABLE_TEST2), 2)
	if err != nil {
		return err
	}
	return nil
}

func (s *SceneTest) CheckTableIncreTestData(db *sql.DB) error {
	return CheckMySQLTableCount(db, s.TestSchemaName, string(TABLE_TEST3), 3)
}
