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) createTiDBClusterBackup(backup *types.TiDBClusterBackup) error {
	t := time.Now().Format(util.TimeFormat)
	backup.Ctime, backup.Utime = t, t

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

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

func (m *mysqlClient) updateTiDBClusterBackup(backup *types.TiDBClusterBackup) error {
	backup.Utime = time.Now().Format(util.TimeFormat)

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

func (m *mysqlClient) getTiDBClusterBackupByID(id int64) (*types.TiDBClusterBackup, error) {
	var backup types.TiDBClusterBackup
	err := m.db.Get(&backup, tidbClusterBackupSelectByID, id)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return &backup, nil
}

func (m *mysqlClient) getTiDBClusterBackupByCatIDAndName(catID int64, name string) (*types.TiDBClusterBackup, error) {
	var backups types.TiDBClusterBackup
	err := m.db.Get(&backups, tidbClusterBackupSelectByCatIDAndName, catID, name)
	if err != nil {
		if strings.Contains(err.Error(), "no rows in result set") {
			return nil, errors.NotFoundf("tidb cluster backup cat id %d and name %s", catID, name)
		}
		return nil, errors.Trace(err)
	}
	return &backups, errors.Trace(err)
}

func (m *mysqlClient) getTiDBClusterBackupByCatID(catID int64) ([]*types.TiDBClusterBackup, error) {
	var backups []*types.TiDBClusterBackup
	rows, err := m.db.Queryx(tidbClusterBackupSelectByCatID, catID)
	if err != nil {
		return nil, errors.Trace(err)
	}
	for rows.Next() {
		var backup types.TiDBClusterBackup
		if err := rows.StructScan(&backup); err != nil {
			return nil, errors.Trace(err)
		}
		backups = append(backups, &backup)
	}

	return backups, errors.Trace(err)
}

const tidbClusterBackupInsert = `
INSERT INTO cat_backup_info (
 name
,namespace
,cluster_name
,cat_id
,state
,create_time
,update_time
,spec
,status
) VALUES (
 :name
,:namespace
,:cluster_name
,:cat_id
,:state
,:create_time
,:update_time
,:spec
,:status
)
`

const tidbClusterBackupUpdate = `
UPDATE cat_backup_info SET
 name = :name
,namespace = :namespace
,cluster_name = :cluster_name
,cat_id = :cat_id
,state = :state
,update_time = :update_time
,spec = :spec
,status = :status
WHERE id = :id
`

const tidbClusterBackupSelectByID = `
SELECT 
 id
,name
,namespace
,cluster_name
,cat_id
,state
,create_time
,update_time
,spec
,status
FROM cat_backup_info
WHERE id = ?
`

const tidbClusterBackupSelectByCatIDAndName = `
SELECT 
 id
,name
,namespace
,cluster_name
,cat_id
,state
,create_time
,update_time
,spec
,status
FROM cat_backup_info
WHERE cat_id = ? AND name = ?
`

const tidbClusterBackupSelectByCatID = `
SELECT 
 id
,name
,namespace
,cluster_name
,cat_id
,state
,create_time
,update_time
,spec
,status
FROM cat_backup_info
WHERE cat_id = ?
`
