// Package regionalservercli add by blacknc <blacknc@163.com> at 2024/09/10 16:17:36
package regionalservercli

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"path/filepath"
	"time"

	"golang.org/x/net/context/ctxhttp"
	spb "google.golang.org/genproto/googleapis/rpc/status"
	grpcstatus "google.golang.org/grpc/status"
	"google.golang.org/protobuf/encoding/protojson"
	"sigs.k8s.io/controller-runtime/pkg/log"
)

type baseServiceHTTPClient struct {
	endpoint     string
	httpClient   *http.Client
	marshalOpt   protojson.MarshalOptions
	unmarshalOpt protojson.UnmarshalOptions
}

func newBaseServiceHTTPClient(endpoint string) *baseServiceHTTPClient {
	return &baseServiceHTTPClient{
		endpoint:   endpoint,
		httpClient: http.DefaultClient,
		marshalOpt: protojson.MarshalOptions{
			UseProtoNames:   false,
			EmitUnpopulated: true,
		},
		unmarshalOpt: protojson.UnmarshalOptions{
			DiscardUnknown: true,
		},
	}
}

func (c *baseServiceHTTPClient) processError(httpstatuscode int, data []byte) error {
	status := new(spb.Status)
	if err := c.unmarshalOpt.Unmarshal(data, status); err != nil {
		return err
	}
	status.Message = fmt.Sprintf("%s;HTTPSTATUSCODE:%v", status.Message, httpstatuscode)
	return grpcstatus.ErrorProto(status)
}

func (c *baseServiceHTTPClient) buildRequestURL(format string, args ...any) string {
	path := fmt.Sprintf(format, args...)
	path = filepath.Join("/api/dedicated/v1", path)
	return fmt.Sprintf("http://%s%s", c.endpoint, path)
}

func (c *baseServiceHTTPClient) doHttpGetRequest(ctx context.Context, url string) (data []byte, err error) {
	startTime := time.Now()
	logger := log.FromContext(ctx)
	defer func() {
		cost := time.Since(startTime).String()
		var logData string
		if len(data) > 200 {
			logData = string(data[:200]) + "..."
		} else {
			logData = string(data)
		}
		if err == nil {
			logger.Info("regional server request succeed", "cost", cost, "method", "GET", "url", url, "response", logData)
		} else {
			logger.Error(err, "regional server request failed", "cost", cost, "method", "GET", "url", url, "response", logData)
		}
	}()

	resp, err := ctxhttp.Get(ctx, c.httpClient, url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	data, err = io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode > 300 {
		return nil, c.processError(resp.StatusCode, data)
	}
	return data, nil
}
