package trafficjobclient

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/pingcap-inc/clinic/pkg/types"
)

// const defaultURL = "https://clinic.pingcap.com/clinic-internal/traffic-mirroring/report"
const defaultURL = "http://clinic-data-service:8087/clinic-internal/traffic-mirroring/report"

type Request struct {
	ReportName  string  `json:"reportName,omitempty"`
	ClusterA    Cluster `json:"clusterA"`
	ClusterB    Cluster `json:"clusterB"`
	CallbackURL string  `json:"callBackUrl"`
	Options     Options `json:"options"`
}

type Cluster struct {
	Region            string            `json:"region,omitempty"`
	Provider          string            `json:"provider,omitempty"`
	DeployType        string            `json:"deployType,omitempty"`
	TenantID          string            `json:"tenantId,omitempty"`
	ProjectID         string            `json:"projectId,omitempty"`
	ClusterID         string            `json:"clusterId"`
	PhysicalClusterID string            `json:"physicalClusterId,omitempty"` // for premium
	DataPlaneID       string            `json:"dataPlaneId,omitempty"`       // for premium
	Alias             string            `json:"alias"`
	URLs              types.ClusterURLs `json:"clusterUrls,omitempty"`
	TimeRange         TimeRange         `json:"timeRange"`
}

type TimeRange struct {
	Start string `json:"start"`
	End   string `json:"end"`
}

type Options struct {
	ReportID       string   `json:"reportId,omitempty"`
	TopN           int      `json:"topN"`
	DigestDiffKeys []string `json:"digestDiffKeys"`
}

type Client struct {
	url string
	c   *http.Client
}

func NewClient(url string) *Client {
	if url == "" {
		url = defaultURL
	}
	return &Client{
		url: url,
		c: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

func (c *Client) URL() string {
	if c == nil {
		return ""
	}
	return c.url
}

func (c *Client) Do(req *Request) error {
	if req == nil {
		return fmt.Errorf("nil request")
	}
	b, err := json.Marshal(req)
	if err != nil {
		return err
	}
	httpReq, err := http.NewRequest("POST", c.url, bytes.NewReader(b))
	if err != nil {
		return err
	}
	httpReq.Header.Set("Content-Type", "application/json")
	resp, err := c.c.Do(httpReq)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("request failed: status=%d body=%s", resp.StatusCode, string(body))
	}
	return nil
}
