package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/pingcap/schrodinger-test/util"
	"github.com/pingcap/schrodinger/pkg/test_client"
	"golang.org/x/net/context"
)

var (
	Pwd            string
	Database       string
	TIDBHost       string
	TIDBStatusPort int
	TIDBPort       int
	Timeout        int
	DDLNumber      int
	Limit          int
)

func init() {
	flag.StringVar(&Pwd, "pwd", "", "password")
	flag.StringVar(&Database, "db", "test", "database")
	flag.StringVar(&TIDBHost, "tidb-host", "", "tidb host")
	flag.IntVar(&TIDBStatusPort, "tidb-status-port", 10080, "tidb status port")
	flag.IntVar(&TIDBPort, "tidb-port", 4000, "tidb server port")
	flag.IntVar(&Timeout, "timeout", 3, "ddl history timeout")
	flag.IntVar(&DDLNumber, "ddl-number", 10000, "ddl number")
	flag.IntVar(&Limit, "limit", 100, "history limit")
}

func main() {
	client.Info("[tibug-59] start...")
	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())
	cli := client.New(ctx, client.ModeOnline)

	// monitoring system exit message
	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	go func() {
		sig := <-sc
		client.Infof("[tibug-59] Got signal [%s] to exist.", sig)
		cancel()
		os.Exit(0)
	}()

	tidbAddr := TIDBHost + ":" + strconv.Itoa(TIDBPort)
	if len(TIDBHost) == 0 {
		tidbAddr = cli.TiDBService()
	}
	dbDNS := fmt.Sprintf("root:%s@tcp(%s)/%s", Pwd, tidbAddr, Database)
	client.Info("dbDNS: ", dbDNS)

	db, err := util.OpenDB(dbDNS, 10)
	if err != nil {
		client.Fatalf("[tibug-59] create db client err %v", err)
	}

	createf := "create table t%v(a int)"
	add1f := "alter table t%v add column (b int)"
	add2f := "alter table t%v add column (c varchar(255))"
	dropf := "alter table t%v drop column b"

	i := 0
	count := 0
	for count < DDLNumber {
		i++

		// exec ddl sql
		sqls := []string{fmt.Sprintf(createf, i), fmt.Sprintf(add1f, i), fmt.Sprintf(add2f, i), fmt.Sprintf(dropf, i)}
		for _, sql := range sqls {
			client.Infof("sql: %v", sql)
			if _, err := db.Exec(sql); err != nil {
				client.Fatalf("[tibug-59] exec table err %v", err)
			}
			count++
			if count >= DDLNumber {
				break
			}
		}

	}

	tidbStatusAddr := TIDBHost + ":" + strconv.Itoa(TIDBStatusPort)
	if len(TIDBHost) == 0 {
		tidbStatusAddr = strings.Split(cli.TiDBService(), ":")[0] + ":" + strconv.Itoa(TIDBStatusPort)
	}

	urlLimit := fmt.Sprintf("http://%v/ddl/history?limit=%v", tidbStatusAddr, Limit)
	for i := 0; i < 3; i++ {
		getHistory(urlLimit)
	}
}

func getHistory(url string) {
	c := http.Client{Timeout: time.Duration(Timeout) * time.Second}
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		client.Fatalf("create new http request err %v", err)
	}

	beginTime := time.Now().UnixNano()
	resp, err := c.Do(request)
	if err != nil {
		client.Fatalf("request history err %v", err)
	}
	defer func() {
		resp.Body.Close()

		endTime := time.Now().UnixNano()
		client.Infof("get url: %v, time: %v ms", url, (endTime-beginTime)/1e6)
	}()

	if resp.StatusCode != http.StatusOK {
		client.Fatalf("http response code %v", resp.StatusCode)
	}

	if _, err := ioutil.ReadAll(resp.Body); err != nil {
		client.Fatalf("read response data err %v", err)
	}
}
