package clinic_internal_api

import (
	"context"
	"fmt"
	"net/url"
	"strconv"
	"strings"
)

// TopRUTarget contains the server-resolved O11y target for the Top RU
// capability. Callers must not supply or override these routing values.
type TopRUTarget struct {
	BaseURL string             `json:"baseUrl"`
	Headers TopRUTargetHeaders `json:"headers"`
}

// TopRUTargetHeaders contains the allowlisted routing context generated by
// Clinic for requests to the resolved Top RU target. ProjectID and
// DeployTypeV2 can be empty for legacy cluster metadata.
type TopRUTargetHeaders struct {
	Env          string `json:"env"`
	BizType      string `json:"bizType"`
	Provider     string `json:"provider"`
	Region       string `json:"region"`
	OrgID        string `json:"orgId"`
	ProjectID    string `json:"projectId"`
	ClusterID    string `json:"clusterId"`
	DeployType   string `json:"deployType"`
	DeployTypeV2 string `json:"deployTypeV2"`
}

// GetTopRUTarget resolves the canonical O11y Top RU target for a logical
// TiDB Cloud organization and cluster.
func (c *Client) GetTopRUTarget(ctx context.Context, orgID uint64, clusterID string) (*TopRUTarget, error) {
	if orgID == 0 {
		return nil, fmt.Errorf("org_id must be a positive integer")
	}

	var result TopRUTarget
	err := c.getResource(ctx, []string{
		"orgs",
		strconv.FormatUint(orgID, 10),
		"clusters",
		clusterID,
		"targets",
		"top-ru",
	}, nil, &result)
	if err != nil {
		return nil, err
	}
	if err := result.validate(orgID, clusterID); err != nil {
		return nil, fmt.Errorf("validate Clinic internal Top RU target response: %w", err)
	}
	return &result, nil
}

func (t *TopRUTarget) validate(orgID uint64, clusterID string) error {
	if t == nil {
		return fmt.Errorf("response is required")
	}
	required := []struct {
		name  string
		value string
	}{
		{name: "baseUrl", value: t.BaseURL},
		{name: "headers.env", value: t.Headers.Env},
		{name: "headers.bizType", value: t.Headers.BizType},
		{name: "headers.provider", value: t.Headers.Provider},
		{name: "headers.region", value: t.Headers.Region},
		{name: "headers.orgId", value: t.Headers.OrgID},
		{name: "headers.clusterId", value: t.Headers.ClusterID},
		{name: "headers.deployType", value: t.Headers.DeployType},
	}
	for _, field := range required {
		if strings.TrimSpace(field.value) == "" {
			return fmt.Errorf("%s is required", field.name)
		}
	}

	baseURL, err := url.Parse(t.BaseURL)
	if err != nil || baseURL.Opaque != "" || (baseURL.Scheme != "http" && baseURL.Scheme != "https") ||
		baseURL.Host == "" || baseURL.Hostname() == "" {
		return fmt.Errorf("baseUrl must be an absolute HTTP(S) URL")
	}
	if baseURL.User != nil || baseURL.RawQuery != "" || baseURL.ForceQuery || baseURL.Fragment != "" ||
		(baseURL.Path != "" && baseURL.Path != "/") {
		return fmt.Errorf("baseUrl must contain only scheme and host")
	}
	if t.Headers.OrgID != strconv.FormatUint(orgID, 10) {
		return fmt.Errorf("headers.orgId does not match the requested organization")
	}
	if t.Headers.ClusterID != clusterID {
		return fmt.Errorf("headers.clusterId does not match the requested cluster")
	}
	return nil
}
