package tidb_management_service

import (
	"context"
	"fmt"
	regionalpb "github.com/tidbcloud/tidb-management-service/api/spec/regional/dedicated/v1"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	spb "google.golang.org/genproto/googleapis/rpc/status"
	"google.golang.org/grpc"
	grpcstatus "google.golang.org/grpc/status"
	"google.golang.org/protobuf/encoding/protojson"
	"io"
	"net/http"
	"net/url"
)

// @Time    : 2024/9/6 15:04
// @Author  : lvhongmeng

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

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

func (c *AppBoxServiceHTTPClient) ListAppBoxes(ctx context.Context, in *regionalpb.ListAPPBoxesRequest, opts ...grpc.CallOption) (*regionalpb.ListAPPBoxesResponse, error) {
	query := make(url.Values)
	if in.GetTenantId() != "" {
		query.Add("tenantId", in.GetTenantId())
	}
	if in.GetProjectId() != "" {
		query.Add("projectId", in.GetProjectId())
	}
	if in.GetClusterId() != "" {
		query.Add("clusterId", in.GetClusterId())
	}
	tilog.Info(ctx, "ListAppBoxes url", zap.String("url", fmt.Sprintf("%s/api/dedicated/v1/appboxes?%s", c.endpoint, query.Encode())))
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/api/dedicated/v1/appboxes?%s", c.endpoint, query.Encode()), nil)
	if err != nil {
		return nil, err
	}
	resp, err := c.httpClient.Do(req)
	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)
	}
	out := new(regionalpb.ListAPPBoxesResponse)
	if err := c.unmarshalOpt.Unmarshal(data, out); err != nil {
		return nil, err
	}
	return out, nil
}

func (c *AppBoxServiceHTTPClient) 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)
}
