package prepare

import (
	"database/sql"
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/schrodinger-test/util"
	client "github.com/pingcap/schrodinger/pkg/test_client"
)

const sysbenchPrepareCMD = "sysbench oltp_read_write --mysql-host=%s --mysql-port=%d --mysql-user=%s --mysql-db=%s " +
	"--tables=%d --table-size=%d --db-driver=mysql --threads=%d --percentile=99 prepare"

func CreateDBIfNeeded(db *sql.DB, dbName string) error {
	stmt := fmt.Sprintf("create database IF NOT EXISTS %s", dbName)
	_, err := db.Exec(stmt)
	if err != nil {
		client.Errorf("[backup] create database, exec %s failed: %v", stmt, err)
		return errors.Trace(err)
	}
	return nil
}

func PrepareData(cli *client.Client, dbName string, tables int, tableSize int) error {
	lbService := cli.TiDBService()
	addrs := strings.Split(strings.TrimSpace(lbService), ":")
	if len(addrs) < 2 {
		client.Errorf("[backup] addr %s is invalid", addrs)
	}
	port, err := strconv.Atoi(addrs[1])
	if err != nil {
		client.Errorf("[backup] addr %s is invalid", addrs)
	}

	dbDSN := fmt.Sprintf("root:@tcp(%s)/test", lbService)
	db, err := util.OpenDB(dbDSN, 1)
	if err != nil {
		client.Errorf("[backup] create db client error %v", err)
		return errors.Trace(err)
	}

	if err = CreateDBIfNeeded(db, dbName); err != nil {
		return errors.Trace(err)
	}

	cmdStr := fmt.Sprintf(sysbenchPrepareCMD, addrs[0], port,
		"root", dbName, tables, tableSize, 256)
	client.Infof("[backup] start to prepare data, exec [%s]", cmdStr)
	if _, err := Execute(cmdStr); err != nil {
		return errors.Trace(err)
	}

	return nil
}

func Execute(cmdStr string) (string, error) {
	cmd := exec.Command("/bin/sh", "-c", cmdStr)
	buf, err := cmd.CombinedOutput()
	if err != nil {
		client.Errorf("[backup] execute %s: %s \n, output: %s", cmdStr, err, string(buf))
	}
	return string(buf), errors.Trace(err)
}
