package client

import (
	"encoding/json"
	"fmt"
	"strings"

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

// CreateConfigTemplate creates a config template by schrodinger api
func (c *Client) CreateConfigTemplate(ct *types.TiDBClusterConfigTemplate) (*types.TiDBClusterConfigTemplate, error) {
	t, err := json.Marshal(ct)
	if err != nil {
		return nil, errors.Trace(err)
	}

	url := fmt.Sprintf("%s/cat_config/templates", c.cfg.Addr)
	_, err = util.PostAndExtract(c.client, url, t)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return ct, nil
}

// UpdateConfigTemplate updates a config template by schrodinger api
func (c *Client) UpdateConfigTemplate(ct *types.TiDBClusterConfigTemplate) (*types.TiDBClusterConfigTemplate, error) {
	t, err := json.Marshal(ct)
	if err != nil {
		return nil, errors.Trace(err)
	}

	url := fmt.Sprintf("%s/cat_config/templates/%d", c.cfg.Addr, ct.ID)
	_, err = util.PutAndExtract(c.client, url, t)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return ct, nil
}

// SetConfigTemplate sets a Config templates by schrodinger api,
// if the config template is exists,
// `SetConfigTemplate` will update this config template
func (c *Client) SetConfigTemplate(ct *types.TiDBClusterConfigTemplate) (*types.TiDBClusterConfigTemplate, error) {
	getURL := fmt.Sprintf("%s/cat_config/templates/name/%s", c.cfg.Addr, ct.Name)
	respData, err := util.GetAndExtract(c.client, getURL)
	if err == nil {
		respConfigTempalte := &types.TiDBClusterConfigTemplate{}
		if err = json.Unmarshal(respData, respConfigTempalte); err != nil {
			return nil, errors.Trace(err)
		}

		ct.ID = respConfigTempalte.ID
		return c.UpdateConfigTemplate(ct)
	}

	if strings.Contains(err.Error(), "not found") {
		return c.CreateConfigTemplate(ct)
	}

	return nil, errors.Trace(err)
}

// ListConfigTemplates lists config templates
func (c *Client) ListConfigTemplates(limit, offset int64) (types.TiDBClusterConfigTemplates, error) {
	listURL := fmt.Sprintf("%s/cat_config/templates?size=%d&offset=%d", c.cfg.Addr, limit, offset)
	respData, err := util.GetAndExtract(c.client, listURL)
	if err != nil {
		return nil, errors.Trace(err)
	}

	listData := api.ListData{}
	if err = json.Unmarshal(respData, &listData); err != nil {
		return nil, errors.Trace(err)
	}

	templatesJSON, _ := json.Marshal(listData.List)

	var respConfigs types.TiDBClusterConfigTemplates
	if err = json.Unmarshal(templatesJSON, &respConfigs); err != nil {
		return nil, errors.Trace(err)
	}

	return respConfigs, nil
}
