package utils

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"time"
)

type ClinicClient struct {
	client *http.Client
	addr   string
}

func NewClinicClient(addr string) *ClinicClient {
	return &ClinicClient{
		client: &http.Client{
			Timeout: 5 * time.Second,
		},
		addr: addr,
	}
}

type Organization struct {
	ID   string `json:"id,omitempty"`
	Name string `json:"name"`
}

type Cluster struct {
	ID           string              `json:"id"`
	Name         string              `json:"name"`
	FeatureGates ClusterFeatureGates `json:"featureGates"`
}

type ClusterFeatureGates struct {
	LogsEnabled              bool `json:"logsEnabled"`
	MaterializedViewEnabled  bool `json:"materializedViewEnabled"`
	SlowQueryEnabled         bool `json:"slowQueryEnabled"`
	SlowQueryVisualEnabled   bool `json:"slowQueryVisualEnabled"`
	TopSQLEnabled            bool `json:"topSQLEnabled"`
	TopRUEnabled             bool `json:"topRUEnabled"`
	ConProfEnabled           bool `json:"conProfEnabled"`
	BenchmarkReportEnabled   bool `json:"benchmarkReportEnabled"`
	ComparisonReportEnabled  bool `json:"comparisonReportEnabled"`
	SystemCheckReportEnabled bool `json:"systemCheckReportEnabled"`
}

func (c *ClinicClient) GetClinicOrgId(dbaasTenantId uint64) (uint64, error) {
	req, err := http.NewRequest("GET",
		fmt.Sprintf("http://%s/clinic/api/v1/orgs/external/%d", c.addr, dbaasTenantId),
		nil)
	if err != nil {
		return 0, fmt.Errorf("failed to create http request, %w", err)
	}
	resp, err := c.client.Do(req)
	if err != nil {
		return 0, fmt.Errorf("failed to get clinic org id, %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return 0, fmt.Errorf("failed to get clinic org id, status code: %d", resp.StatusCode)
	}
	var org Organization
	if err := json.NewDecoder(resp.Body).Decode(&org); err != nil {
		return 0, fmt.Errorf("failed to decode response body, %w", err)
	}
	orgId, err := strconv.ParseUint(org.ID, 10, 64)
	if err != nil {
		return 0, fmt.Errorf("failed to parse clinic org id, %w", err)
	}
	return orgId, nil
}

func (c *ClinicClient) GetCluster(clinicOrgId, clusterId uint64) (*Cluster, error) {
	req, err := http.NewRequest("GET",
		fmt.Sprintf("http://%s/clinic/api/v1/orgs/%d/clusters/%d", c.addr, clinicOrgId, clusterId),
		nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create http request, %w", err)
	}
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to get cluster, %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get cluster, status code: %d", resp.StatusCode)
	}
	var cluster Cluster
	if err := json.NewDecoder(resp.Body).Decode(&cluster); err != nil {
		return nil, fmt.Errorf("failed to decode response body, %w", err)
	}
	return &cluster, nil
}
