package storage

import (
	"strings"
	"time"

	"github.com/juju/errors"
	"github.com/pingcap/schrodinger/pkg/types"
	"github.com/pingcap/schrodinger/util"
)

/* ---------------- mysql storage ------------------*/

func (m *mysqlClient) createTiDBClusterConfigTemplate(config *types.TiDBClusterConfigTemplate) error {
	t := time.Now().Format(util.TimeFormat)
	config.Utime, config.Ctime = t, t

	result, err := m.db.NamedExec(tidbClusterConfigTemplateInsert, config)
	if err != nil {
		return errors.Trace(err)
	}

	config.ID, err = result.LastInsertId()
	if err != nil {
		return errors.Trace(err)
	}
	return nil
}

func (m *mysqlClient) updateTiDBClusterConfigTemplate(config *types.TiDBClusterConfigTemplate) error {
	config.Utime = time.Now().Format(util.TimeFormat)

	if _, err := m.db.NamedExec(tidbClusterConfigTemplateUpdate, config); err != nil {
		return errors.Trace(err)
	}
	return nil
}

func (m *mysqlClient) deleteTiDBClusterConfigTemplate(id int64) error {
	if _, err := m.db.Exec("UPDATE config_template SET update_time = now(), is_deleted = true WHERE id = ?", id); err != nil {
		return errors.Trace(err)
	}
	return nil
}

func (m *mysqlClient) listTiDBClusterConfigTemplates() (types.TiDBClusterConfigTemplates, error) {
	var tidbClusterConfigTemplates types.TiDBClusterConfigTemplates
	rows, err := m.db.Queryx(tidbClusterConfigTemplateSelect)
	if err != nil {
		return nil, errors.Trace(err)
	}

	for rows.Next() {
		var configTemplate types.TiDBClusterConfigTemplate
		if err := rows.StructScan(&configTemplate); err != nil {
			return nil, errors.Trace(err)
		}
		tidbClusterConfigTemplates = append(tidbClusterConfigTemplates, &configTemplate)
	}

	return tidbClusterConfigTemplates, nil
}

func (m *mysqlClient) getTiDBClusterConfigTemplateByID(ID int64) (*types.TiDBClusterConfigTemplate, error) {
	var tiDBClusterConfigTemplate types.TiDBClusterConfigTemplate

	if err := m.db.Get(&tiDBClusterConfigTemplate, tidbClusterConfigTemplateSelectByID, ID); err != nil {
		if strings.Contains(err.Error(), "no rows in result set") {
			return nil, errors.NotFoundf("tidb cluster config template %d", ID)
		}
		return nil, errors.Trace(err)
	}

	return &tiDBClusterConfigTemplate, nil
}

func (m *mysqlClient) getTiDBClusterConfigTemplateByName(name string) (*types.TiDBClusterConfigTemplate, error) {
	var tiDBClusterConfigTemplate types.TiDBClusterConfigTemplate

	if err := m.db.Get(&tiDBClusterConfigTemplate, tidbClusterConfigTemplateSelectByName, name); err != nil {
		if strings.Contains(err.Error(), "no rows in result set") {
			return nil, errors.NotFoundf("tidb cluster config template %s", name)
		}
		return nil, errors.Trace(err)
	}

	return &tiDBClusterConfigTemplate, nil
}

func (m *mysqlClient) getTiDBClusterConfigTemplatesByTag(tag string) (types.TiDBClusterConfigTemplates, error) {
	var tidbClusterConfigTemplates types.TiDBClusterConfigTemplates
	rows, err := m.db.Queryx(tidbClusterConfigTemplateSelectByTag, tag)
	if err != nil {
		return nil, errors.Trace(err)
	}

	for rows.Next() {
		var configTemplate types.TiDBClusterConfigTemplate
		if err := rows.StructScan(&configTemplate); err != nil {
			return nil, errors.Trace(err)
		}
		tidbClusterConfigTemplates = append(tidbClusterConfigTemplates, &configTemplate)
	}

	return tidbClusterConfigTemplates, nil
}

const tidbClusterConfigTemplateInsert = `
INSERT INTO config_template (
 name
,create_time
,update_time
,tag
,description
,content
,is_deleted
) VALUES (
 :name
,:create_time
,:update_time
,:tag
,:description
,:content
,:is_deleted
)
`

const tidbClusterConfigTemplateUpdate = `
UPDATE config_template SET
 name = :name
,update_time = :update_time
,tag = :tag
,description = :description
,content = :content
,is_deleted = :is_deleted
WHERE id = :id
`

const tidbClusterConfigTemplateSelect = `
SELECT
 id
,name
,create_time
,update_time
,tag
,description
,content
,is_deleted
FROM config_template
WHERE is_deleted = false
`

const tidbClusterConfigTemplateSelectByID = `
SELECT
 id
,name
,create_time
,update_time
,tag
,description
,content
,is_deleted
FROM config_template
WHERE is_deleted = false AND id = ?
`

const tidbClusterConfigTemplateSelectByName = `
SELECT
 id
,name
,create_time
,update_time
,tag
,description
,content
,is_deleted
FROM config_template
WHERE is_deleted = false AND name = ?
`

const tidbClusterConfigTemplateSelectByTag = `
SELECT
 id
,name
,create_time
,update_time
,tag
,description
,content
,is_deleted
FROM config_template
WHERE is_deleted = false AND tag = ?
`
