package middleware

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/notifiermgr/event"
	"github.com/pingcap/schrodinger/notifiermgr/util"
	"github.com/pingcap/schrodinger/pkg/types"
)

type destroyResponse struct {
	Code    int     `json:"code"`
	Message *string `json:"message"`
}

func destroyExperiment(ep *types.ExperimentProcess, baseDomain string) error {
	url := fmt.Sprintf("https://%s/boxes/%d/experiments/%d/destroy", baseDomain, ep.BoxID, ep.ID)
	resp, err := http.Post(url, "application/json", nil)

	if err != nil {
		return err
	}

	buf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	responseBody := new(destroyResponse)
	err = json.Unmarshal(buf, responseBody)

	if responseBody.Code != 200 {
		if responseBody.Message == nil {
			return errors.New("Field message in an Error return of manager API is nil")
		}
		return errors.New(*responseBody.Message)
	}

	return nil
}

func destroyExpDriver(configPtr *interface{}) Middleware {
	input := make(chan event.Event)
	output := make(chan event.Event)

	config, err := util.GetSimpleMap(configPtr)
	if err != nil {
		log.Errorf("Error while mapping a config to map: %s", errors.ErrorStack(err))
	}

	baseDomain := config.GetString("baseDomain")
	if baseDomain == nil {
		return nil
	}
	go func() {
		for ev := range input {
			ep, ok := ev.(*types.ExperimentProcess)
			if !ok {
				log.Error("Input of generateExpReportDriver is not an *ExperimentProcess")
				continue
			}

			err := destroyExperiment(ep, *baseDomain)
			if err != nil {
				log.Errorf("Error while requesting to destroy experiment %s", errors.ErrorStack(err))
				continue
			}

			output <- ep
		}
	}()

	return &RealMiddleware{
		input,
		output,
	}
}
