package steps

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/pingcap/errors"
	"github.com/pingcap/log"
	"github.com/pingcap/test-infra/caselib/pkg/mysql"
	"github.com/pingcap/test-infra/caselib/pkg/utils"
	apiresource "github.com/pingcap/test-infra/common/model/resource"
	"github.com/pingcap/test-infra/sdk/core"
	"github.com/pingcap/test-infra/sdk/resource"
)

type TiDBVariable struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

var TiDBVariableList []TiDBVariable

type globalVariable struct {
	Opts *[]TiDBVariable
	res  []*apiresource.ResourceHandle
}

func (g globalVariable) String() string {
	return fmt.Sprintf("Config tidb global variables, options=%+v", *g.Opts)
}

// Execute change tidb global variable based on parameters
// example parameters: TI_PARAM_STR_global_variable: [{"name": "tidb_enable_list_partition", "value": "on"}]
func (g globalVariable) Execute(ctx context.Context) error {
	for _, res := range g.res {
		log.Info(fmt.Sprintf("Config tidb global variable for %s", res.Name))
		mysqlInst := utils.Try(core.ResolveResourceHandle(res)).(resource.MySQLCompatible)
		db := utils.Try(mysqlInst.GetDB("")).(*sql.DB)
		defer db.Close()
		client := mysql.NewMySQLClient(db)
		for _, v := range *g.Opts {
			_, err := client.Query(fmt.Sprintf("set global %s=%s", v.Name, v.Value))
			if err != nil {
				return errors.Trace(err)
			}
		}
	}
	return nil
}

func (b *Builder) ConfigGlobalVariable(opts *[]TiDBVariable, resHandles ...*apiresource.ResourceHandle) *Builder {
	b.steps = append(b.steps, globalVariable{opts, resHandles})
	return b
}
