package common

import (
	"database/sql"
	"fmt"
	"github.com/pingcap/log"
)

// some common sql move to pkg/sql/statement.go
// should remove the sql here?
const (
	DDL_TEMPLATE_DROP_DATABASE   = "DROP DATABASE IF EXISTS `%s`"
	DDL_TEMPLATE_CREATE_DATABASE = "CREATE DATABASE IF NOT EXISTS `%s`"
	DDL_ALERT_GC_TIME            = "SET GLOBAL tidb_gc_life_time = `%s`;"

	DDL_TEMPLATE_CREATE_TABLE_WITH_UNIQUE_KEY    = "CREATE TABLE IF NOT EXISTS `%s`.`%s` (`id` int(11) not null, `c` int(11) default null, primary key (`id`), unique key `%s_c` (`c`))"
	DDL_TEMPLATE_CREATE_TABLE_WITHOUT_UNIQUE_KEY = "CREATE TABLE IF NOT EXISTS `%s`.`%s` (`id` int(11) not null, `c` int(11) default null)"
)

const (
	DML_TEMPLATE_INSERT_ONE_ROW   = "insert into `%s`.`%s` values (1,1)"
	DML_TEMPLATE_INSERT_TWO_ROW   = "insert into `%s`.`%s` values (1,1),(2,2)"
	DML_TEMPLATE_INSERT_THREE_ROW = "insert into `%s`.`%s` values (1,1),(2,2),(3,3)"

	DML_TEMPLATE_COUNT_TABLE = "select count(*) from %s.%s"
)

func ExecDDL(db *sql.DB, sql string) (sql.Result, error) {
	return db.Exec(sql)
}

func ExecDML(db *sql.DB, sql string) (*sql.Rows, error) {
	return db.Query(sql)
}

func DropSchema(db *sql.DB, schema string) error {
	_, err := ExecDDL(db, fmt.Sprintf(DDL_TEMPLATE_DROP_DATABASE, schema))
	if err != nil {
		return err
	}
	return nil
}

func CreateSchema(db *sql.DB, schema string) error {
	_, err := ExecDDL(db, fmt.Sprintf(DDL_TEMPLATE_CREATE_DATABASE, schema))
	if err != nil {
		return err
	}
	return nil
}

func SetGCTime(db *sql.DB, time string) error {
	log.Info(fmt.Sprintf(DDL_ALERT_GC_TIME, time))
	_, err := ExecDDL(db, fmt.Sprintf(DDL_ALERT_GC_TIME, time))
	if err != nil {
		return err
	}
	return nil
}

func CheckMySQLTableCount(db *sql.DB, schema string, table string, expectCount int) error {
	actualCount, err := CountMySQLTable(db, schema, table)
	if err != nil {
		return err
	}
	if actualCount != expectCount {
		return fmt.Errorf("schema: %s, table is %s, expect count is %d, actual count is %d", schema, table, expectCount, actualCount)
	}
	return nil
}

func CountMySQLTable(db *sql.DB, schema string, table string) (int, error) {
	rows, err := ExecDML(db, fmt.Sprintf(DML_TEMPLATE_COUNT_TABLE, schema, table))
	if err != nil {
		return 0, err
	}
	defer rows.Close()
	var count int
	if !rows.Next() {
		return 0, nil
	}
	err = rows.Scan(&count)
	if err != nil {
		return 0, err
	}
	return count, nil
}

func CreateTableWithUniqueKey(db *sql.DB, schema string, table string) error {
	_, err := ExecDDL(db, fmt.Sprintf(DDL_TEMPLATE_CREATE_TABLE_WITH_UNIQUE_KEY, schema, table, table))
	if err != nil {
		return err
	}
	return nil
}

func CreateTableWithoutUniqueKey(db *sql.DB, schema string, table string) error {
	_, err := ExecDDL(db, fmt.Sprintf(DDL_TEMPLATE_CREATE_TABLE_WITHOUT_UNIQUE_KEY, schema, table))
	if err != nil {
		return err
	}
	return nil
}

func InsertDataToTable(db *sql.DB, template string, schema string, table string) error {
	_, err := ExecDML(db, fmt.Sprintf(template, schema, table))
	if err != nil {
		return err
	}
	return nil
}
