package tiup_upgrade

import (
	"context"
	"fmt"
	"net/url"
	"time"

	"database/sql"

	. "github.com/pingcap/endless/pkg/matcher"
	"github.com/pingcap/endless/pkg/workloadnode"
	"github.com/pingcap/log"

	_ "github.com/go-sql-driver/mysql"
	. "github.com/onsi/gomega"
	. "github.com/pingcap/endless/pkg/workloadnode/tiup"
	"github.com/pingcap/test-infra/sdk/core"
	"github.com/pingcap/test-infra/sdk/resource"
	_ "github.com/pingcap/test-infra/sdk/resource/impl/k8s" // register k8s impl

	_ "github.com/pingcap/endless/pkg/client/tidb"
	"go.uber.org/zap"
)

func WKLD_BANK_RUN(
	cluster *TiUPCluster,
	ctx core.TestContext,
	runtime string,
) {
	db := Try(cluster.GetDB("test")).(*sql.DB)
	defer db.Close()
	Try(db.Query("drop database if exists bank;"))
	Try(db.Query("create database bank;"))
	dbURL, err := cluster.ServiceURL(resource.DBAddr)
	must(err)
	log.Info("dbDSN info:", zap.String("dbdsn:", dbURL.Host))

	gorandgen := ctx.Resource("wkload").(resource.WorkloadNode)
	// dbDSN := "tiup-peer:3390"
	dbDSN := dbURL.Host
	runCmd := fmt.Sprintf(`mkdir -p /root/wkload/precheck/;/tools/bank/run.sh init '%s' 100 60 bank > /root/wkload/precheck/bank.log 2>&1;`, dbDSN)
	duration := 10 * time.Hour
	ctx2, cancel := context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 := workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	Expect(cmd1.Run(gorandgen)).Should(BeNil())
	runCmd = fmt.Sprintf(`mkdir -p /root/wkload/postcheck/;nohup /tools/bank/run.sh run '%s' 100 %s bank > /root/wkload/postcheck/bank.log 2>&1`, dbDSN, runtime)
	cmd1 = workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	Expect(cmd1.Run(gorandgen)).Should(BeNil())

}
func WKLD_BANK_CHECK(
	ctx core.TestContext,
) {
	gorandgen := ctx.Resource("wkload").(resource.WorkloadNode)
	// dbDSN := "tiup-peer:3390"
	// check panic in result
	runCmd := fmt.Sprintf(`grep "fail" /tools/bank/nohup.out | wc -l`)
	duration := 10 * time.Hour
	ctx2, cancel := context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 := workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	Expect(cmd1.Run(gorandgen)).Should(BeNil())

}

func WKLD_TPTEST(
	cluster *TiUPCluster,
	ctx core.TestContext,
	flag string,
) {
	if flag == "precheck" {
		db := Try(cluster.GetDB("test")).(*sql.DB)
		defer db.Close()
		Try(db.Query("drop database if exists tptest;"))
		Try(db.Query("create database tptest;"))
	}
	mysqlDB = "tptest"
	gorandgen := ctx.Resource("wkload").(resource.WorkloadNode)
	dbURL := Try(cluster.ServiceURL(resource.DBAddr)).(*url.URL)
	log.Info("dbDSN info:", zap.String("dbdsn:", dbURL.Host))
	// dbDSN := "tiup-peer:3390"
	var runCmd string
	if flag == "precheck" {
		runCmd = fmt.Sprintf(`mkdir -p /root/wkload/precheck/;/tools/tp-test/tp-test/run.sh gen '%s' '%s' tptest %s > /root/wkload/precheck/tptest.log 2>&1`, dbURL.Host, mysqlDsn, mysqlDB)
	} else {
		runCmd = fmt.Sprintf(`mkdir -p /root/wkload/postcheck/;/tools/tp-test/tp-test/run.sh run '%s' '%s' tptest %s >> /root/wkload/postcheck/tptest.log 2>&1`, dbURL.Host, mysqlDsn, mysqlDB)
	}
	duration := 10 * time.Hour
	ctx2, cancel := context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 := workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	err := cmd1.Run(gorandgen)
	if err != nil {
		log.Info("run tptest result: ", zap.String("err:", err.Error()))
	}
	// check panic in log file
	runCmd = fmt.Sprintf(`grep "panic" /root/wkload/%s/tptest.log | wc -l`, flag)
	duration = 10 * time.Hour
	ctx2, cancel = context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 = workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	Expect(cmd1.Run(gorandgen)).Should(BeNil())
}

func WKLD_TPCH(
	cluster *TiUPCluster,
	ctx core.TestContext,
	flag string,
) {
	if flag == "precheck" {
		db := Try(cluster.GetDB("test")).(*sql.DB)
		defer db.Close()
		Try(db.Query("drop database if exists tpch;"))
		Try(db.Query("create database tpch;"))
	}

	gorandgen := ctx.Resource("wkload").(resource.WorkloadNode)
	// dbip := "tiup-peer.testbed-upgrade-fthwr"
	// dbport := "3390"
	dbURL := Try(cluster.ServiceURL(resource.DBAddr)).(*url.URL)
	log.Info("db info:", zap.String("dbIP:", dbURL.Hostname()), zap.String("db port:", dbURL.Port()))

	var runCmd string
	if flag == "precheck" {
		runCmd = fmt.Sprintf(`mkdir -p /root/wkload/precheck/;/tools/go-tpc/run.sh prepare %s %s 60s tpch > /root/wkload/precheck/tpch.log 2>&1`, dbURL.Hostname(), dbURL.Port())
	} else {
		runCmd = fmt.Sprintf(`mkdir -p /root/wkload/postcheck/;/tools/go-tpc/run.sh run %s %s 60s tpch > /root/wkload/postcheck/tpch.log 2>&1`, dbURL.Hostname(), dbURL.Port())
	}
	duration := 60 * time.Second
	ctx2, cancel := context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 := workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	err := cmd1.Run(gorandgen)
	if err != nil {
		log.Info("run tpch result: ", zap.String("err:", err.Error()))
	}
	// check panic in log file
	runCmd = fmt.Sprintf(`grep "panic" /root/wkload/%s/tpch.log | wc -l`, flag)
	duration = 10 * time.Hour
	ctx2, cancel = context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 = workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	Expect(cmd1.Run(gorandgen)).Should(BeNil())
}

func WKLD_RANDGEN(
	cluster *TiUPCluster,
	ctx core.TestContext,
	flag string,
) {
	if flag == "precheck" {
		db := Try(cluster.GetDB("test")).(*sql.DB)
		defer db.Close()
		Try(db.Query("drop database if exists randgen;"))
		Try(db.Query("create database randgen;"))
	}

	gorandgen := ctx.Resource("wkload").(resource.WorkloadNode)
	dbURL := Try(cluster.ServiceURL(resource.DBAddr)).(*url.URL)
	log.Info("dbDSN info:", zap.String("dbdsn:", dbURL.Host))
	// dbDSN := "tiup-peer:3390"
	mysqlDB = "randgen"
	var goRandgenCmd string
	if flag == "precheck" {
		goRandgenCmd = fmt.Sprintf(`mkdir -p /root/wkload/precheck/;/tools/go-randgen-master/run.sh gendata '%s' '%s' randgen %s > /root/wkload/precheck/randgen.log 2>&1`, dbURL.Host, mysqlDsn, mysqlDB)
	} else {
		goRandgenCmd = fmt.Sprintf(`mkdir -p /root/wkload/postcheck/;/tools/go-randgen-master/run.sh exec '%s' '%s' randgen %s>> /root/wkload/postcheck/randgen.log 2>&1`, dbURL.Host, mysqlDsn, mysqlDB)
	}
	duration := 10 * time.Hour
	ctx2, cancel := context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 := workloadnode.CommandContext(ctx2, goRandgenCmd)
	defer cmd1.Stop()
	err := cmd1.Run(gorandgen)
	if err != nil {
		log.Info("run randgen result: ", zap.String("err:", err.Error()))
	}

	// check panic in log file
	runCmd := fmt.Sprintf(`grep "panic" /root/wkload/%s/randgen.log | wc -l`, flag)
	duration = 10 * time.Hour
	ctx2, cancel = context.WithTimeout(ctx, duration)
	defer cancel()
	cmd1 = workloadnode.CommandContext(ctx2, runCmd)
	defer cmd1.Stop()
	Expect(cmd1.Run(gorandgen)).Should(BeNil())

}
