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

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

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

func (m *mysqlClient) updateEndpoint(ept *types.Endpoint) error {
	t := time.Now().Format(util.TimeFormat)
	ept.Utime = t

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

func (m *mysqlClient) listEndpoint() ([]*types.Endpoint, error) {
	var endpoints []*types.Endpoint
	rows, err := m.db.Queryx(endpointSelect)
	if err != nil {
		return nil, errors.Trace(err)
	}

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

	return endpoints, nil
}

func (m *mysqlClient) findEndpointByID(ID int64) (*types.Endpoint, error) {
	var endpoint types.Endpoint
	if err := m.db.Get(&endpoint, endpointSelectByID, ID); err != nil {
		if strings.Contains(err.Error(), "no rows in result set") {
			return nil, errors.NotFoundf("endpoint %d", ID)
		}
		return nil, errors.Trace(err)
	}
	return &endpoint, nil
}

func (m *mysqlClient) deleteEndpoint(id int64) error {
	if _, err := m.db.Exec(endpointDelete, id); err != nil {
		return errors.Trace(err)
	}
	return nil
}

const endpointSelect = `
SELECT
 id
,labels
,type
,name
,value
,create_time
,update_time
FROM endpoint
`

const endpointSelectByID = `
SELECT
 id
,labels
,type
,name
,value
,create_time
,update_time
FROM endpoint
WHERE id = ?
`

const endpointInsert = `
INSERT INTO endpoint (
 labels
,type
,name
,value
,create_time
,update_time
) VALUES (
 :labels
,:type
,:name
,:value
,:create_time
,:update_time
)
`

const endpointUpdate = `
UPDATE endpoint SET 
 labels = :labels
,type = :type
,name = :name
,value = :value
,update_time = :update_time
WHERE id = :id
`

const endpointDelete = `
DELETE FROM endpoint
WHERE id = ?
`
