package apiGatewayConfDeploy

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

const (
	configBearerToken           = "apigeesync_bearer_token"
	trackerConfigStatusEndpoint = "/configurations/status"
	trackerHeartbeatEndpoint    = "/serviceheartbeat/{uuid}"
	trackerRegisterEndpoint     = "/serviceregister/{uuid}"
)

type trackerClientInterface interface {
	putConfigStatus(body *configStatusBody) *trackerResponse
	putRegister(uuid string, body *registerBody) *trackerResponse
	putHeartbeat(uuid, reportedTime string) *trackerResponse
}

type trackerResponse struct {
	code        int
	contentType string
	body        []byte
}

type trackerClient struct {
	trackerBaseUrl string
	clusterId      string
	httpclient     *http.Client
}

func (t *trackerClient) putConfigStatus(reqBody *configStatusBody) *trackerResponse {
	uri, err := url.Parse(t.trackerBaseUrl + trackerConfigStatusEndpoint)
	if err != nil {
		log.Errorf("putConfigStatus failed to parse tracker uri: %v", err)
		return (internalError(err))
	}

	bodyBytes, err := json.Marshal(*reqBody)

	req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(bodyBytes))
	req.Header.Add("Authorization", getBearerToken())
	req.Header.Set("X-Apigee-Consumer-Type", "apid")

	r, err := t.httpclient.Do(req)
	if err != nil {
		log.Errorf("trackerClient communication error: %v", err)
		return (internalError(err))
	}
	defer r.Body.Close()

	return parseTrackerResponse(r)
}

func (t *trackerClient) putRegister(uuid string, reqBody *registerBody) *trackerResponse {
	uri, err := url.Parse(t.trackerBaseUrl + strings.Replace(trackerRegisterEndpoint, "{uuid}", uuid, 1))
	if err != nil {
		log.Errorf("postRegister failed to parse tracker uri: %v", err)
		return (internalError(err))
	}

	body := serviceRegisterBody{
		ClusterId:    t.clusterId,
		Pod:          reqBody.Pod,
		PodType:      reqBody.Type,
		ReportedTime: reqBody.ReportedTime,
		Name:         reqBody.Name,
		Type:         reqBody.Type,
	}

	bodyBytes, err := json.Marshal(body)
	if err != nil {
		return (internalError(err))
	}

	req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(bodyBytes))
	req.Header.Add("Authorization", getBearerToken())
	req.Header.Set("X-Apigee-Consumer-Type", "apid")

	r, err := t.httpclient.Do(req)
	if err != nil {
		log.Errorf("trackerClient communication error: %v", err)
		return (internalError(err))
	}
	defer r.Body.Close()
	return parseTrackerResponse(r)
}

func (t *trackerClient) putHeartbeat(uuid, reported string) *trackerResponse {
	uri, err := url.Parse(t.trackerBaseUrl + strings.Replace(trackerHeartbeatEndpoint, "{uuid}", uuid, 1))
	if err != nil {
		log.Errorf("putHeartbeat failed to parse tracker uri: %v", err)
		return internalError(err)
	}
	req, err := http.NewRequest("PUT", uri.String(), nil)
	req.Header.Add("Authorization", getBearerToken())
	req.Header.Add("reportedTime", reported)
	req.Header.Set("X-Apigee-Consumer-Type", "apid")

	r, err := t.httpclient.Do(req)
	if err != nil {
		log.Errorf("trackerClient communication error: %v", err)
		return internalError(err)
	}
	defer r.Body.Close()
	return parseTrackerResponse(r)
}

func internalError(err error) *trackerResponse {
	res := &trackerResponse{}
	res.code = http.StatusInternalServerError
	res.body = []byte(err.Error())
	return res
}

func getBearerToken() string {
	return "Bearer " + config.GetString(configBearerToken)
}

func parseTrackerResponse(r *http.Response) *trackerResponse {
	trackerBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Errorf("apid failed to read response body: %v", err)
		return (internalError(err))
	}
	res := &trackerResponse{}
	res.contentType = r.Header.Get("Content-type")
	switch r.StatusCode {
	case http.StatusOK:
		res.code = r.StatusCode
		res.body = trackerBody
	case http.StatusUnauthorized, http.StatusForbidden:
		res.code = http.StatusInternalServerError
		res.body = []byte("apid token rejected by tracker")
		log.Errorf("%v: %v, %v", res.body, r.StatusCode, trackerBody)
	case http.StatusNotFound:
		res.code = http.StatusInternalServerError
		res.body = []byte("apid cannot connect to tracker")
		log.Errorf("%v: %v, %v", res.body, r.StatusCode, trackerBody)
	default:
		log.Infof("Abnormal Response from Tracker: %v, %v", r.StatusCode, trackerBody)
		res.code = r.StatusCode
		res.body = trackerBody
	}
	return res
}

type serviceRegisterBody struct {
	ClusterId    string `json:"clusterId"`
	Pod          string `json:"pod"`
	PodType      string `json:"podType"`
	ReportedTime string `json:"reportedTime"`
	Name         string `json:"name"`
	Type         string `json:"type"`
}
