package client

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

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

// UploadPayloadUsingBoxID uploads payload with box id
func (c *Client) UploadPayloadUsingBoxID(payload []byte, name string) error {
	if !c.isOnline() {
		Warnf("only mode online is :. the mode is %s", c.mode)
		return nil
	}

	if err := c.refreshConfig(); err != nil {
		Fatalf("init client config error %v", errors.ErrorStack(err))
	}

	object := &types.Object{
		BoxID:   c.conf.Experiment.BoxID,
		Payload: payload,
		Name:    name,
	}

	data, err := json.Marshal(object)
	if err != nil {
		return errors.Trace(err)
	}

	originData, err := getAndExtract(fmt.Sprintf("%s/boxes/%d/objects/%s", c.managerAddr, c.conf.Experiment.BoxID, name))
	if err != nil && !strings.Contains(err.Error(), "not found") {
		return errors.Trace(err)
	}

	if err != nil && strings.Contains(err.Error(), "not found") {
		_, err = postAndExtract(fmt.Sprintf("%s/objects", c.managerAddr), data)
		if err != nil {
			return errors.Trace(err)
		}
	}

	obj := &types.Object{}

	err = json.Unmarshal(originData, obj)
	if err != nil {
		return errors.Trace(err)
	}

	object.ID = obj.ID

	data, err = json.Marshal(object)
	if err != nil {
		return errors.Trace(err)
	}

	_, err = putAndExtract(fmt.Sprintf("%s/objects/%d", c.managerAddr, object.ID), data)

	return errors.Trace(err)
}

// GetPayloadUsingBoxID get object with box id
func (c *Client) GetPayloadUsingBoxID(name string) ([]byte, error) {
	if !c.isOnline() {
		Warnf("only mode online is :. the mode is %s", c.mode)
		return nil, nil
	}

	if err := c.refreshConfig(); err != nil {
		Fatalf("init client config error %v", errors.ErrorStack(err))
	}

	data, err := getAndExtract(fmt.Sprintf("%s/boxes/%d/objects/%s", c.managerAddr, c.conf.Experiment.BoxID, name))
	if err != nil {
		return nil, errors.Trace(err)
	}

	obj := &types.Object{}
	err = json.Unmarshal(data, obj)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return obj.Payload, nil
}
