package shared

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/smarty/assertions"
	"github.com/tidbcloud/observability/test/webconsolee2e/framework"
)

// MetricsQueryRangeNewPathCase test case for querying metrics using new API path (shared)
type MetricsQueryRangeNewPathCase struct{}

// NewMetricsQueryRangeNewPathCase creates a new MetricsQueryRangeNewPathCase instance
func NewMetricsQueryRangeNewPathCase() *MetricsQueryRangeNewPathCase {
	return &MetricsQueryRangeNewPathCase{}
}

func (c *MetricsQueryRangeNewPathCase) Name() string {
	return "MetricsQueryRangeNewPath"
}

func (c *MetricsQueryRangeNewPathCase) Description() string {
	return "Verify metrics query range API (gateway, shared)"
}

// MetricsQueryResponse metrics query response structure
type MetricsQueryResponseNewPath struct {
	Status string                  `json:"status"`
	Data   MetricsQueryDataNewPath `json:"data"`
}

type MetricsQueryDataNewPath struct {
	ResultType string                     `json:"resultType"`
	Result     []MetricsResultItemNewPath `json:"result"`
}

type MetricsResultItemNewPath struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
}

func (c *MetricsQueryRangeNewPathCase) Run(ctx *framework.TestContext) *framework.CaseResult {
	result := framework.NewCaseResult()

	// Get metricsOpenReadUri from shared data (with newPath prefix)
	metricsOpenReadUri, ok := ctx.GetSharedData(KeyNewPathMetricsOpenReadUri)
	if !ok {
		result.AddError("metricsOpenReadUri not found in shared data, please run GetClusterRouteNewPath case first")
		return result
	}

	// Calculate time range: last 30 minutes
	now := time.Now().Unix()
	start := now - 1800 // 30 minutes ago
	end := now

	// Build request URL: {metricsOpenReadUri}query_range?query=...
	// Note: metricsOpenReadUri already ends with /api/v1/
	query := "tidb_server_connections"
	url := fmt.Sprintf("%squery_range?query=%s&start=%d&end=%d&step=60",
		metricsOpenReadUri,
		query,
		start,
		end,
	)
	result.SetRequest("GET", url, nil)

	// Send request with newpath-specific headers
	client := ctx.GetNewPathClient()
	resp, err := client.Get(url)
	if err != nil {
		result.AddError(fmt.Sprintf("Request failed: %v", err))
		return result
	}

	result.SetRequestWithHeaders(result.Request.Method, result.Request.URL, resp.RequestHeaders, result.Request.Body)
	result.SetResponseWithHeaders(resp.StatusCode, resp.GetResponseHeaders(), resp.String())

	// 1. Check common response headers (CORS)
	checker := framework.NewCommonResponseChecker(result, ctx.Origin)
	checker.CheckCORSHeaders(resp)
	checker.CheckStatusCode(resp, 200)

	// 2. Parse response body
	var respBody MetricsQueryResponseNewPath
	if err := json.Unmarshal(resp.Body, &respBody); err != nil {
		result.AddError(fmt.Sprintf("Failed to parse response JSON: %v", err))
		return result
	}

	// 3. Verify status is "success"
	if msg := assertions.ShouldEqual(respBody.Status, "success"); msg != "" {
		result.AddError(fmt.Sprintf("Status should be 'success': %s", msg))
	}

	// 4. Verify resultType is "matrix"
	if msg := assertions.ShouldEqual(respBody.Data.ResultType, "matrix"); msg != "" {
		result.AddError(fmt.Sprintf("ResultType should be 'matrix': %s", msg))
	}

	// 5. Result may be empty if no data, which is acceptable for shared cluster

	return result
}
