package dedicated

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

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

// StmtListCase test case for SQL statements list API
type StmtListCase struct {
	Fields string // fields to query, comma separated
}

// NewStmtListCase creates a new StmtListCase with default fields
func NewStmtListCase() *StmtListCase {
	return &StmtListCase{
		Fields: "digest_text,sum_latency,avg_latency,max_latency,min_latency,exec_count,plan_count,sum_ru,avg_ru",
	}
}

func (c *StmtListCase) Name() string {
	return "StmtList"
}

func (c *StmtListCase) Description() string {
	return "Verify SQL statements list API - /proxy/orgs/{orgID}/clusters/{clusterID}/pd/dashboard/api/statements/list"
}

// StmtListItem represents a single statement item in the list response
type StmtListItem struct {
	DigestText string  `json:"digest_text"`
	SumLatency float64 `json:"sum_latency"`
	AvgLatency float64 `json:"avg_latency"`
	MaxLatency float64 `json:"max_latency"`
	MinLatency float64 `json:"min_latency"`
	ExecCount  int64   `json:"exec_count"`
	PlanCount  int64   `json:"plan_count"`
	SumRU      float64 `json:"sum_ru"`
	AvgRU      float64 `json:"avg_ru"`
}

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

	// Check if ClinicURL is configured
	if ctx.ClinicURL == "" {
		result.AddError("ClinicURL is not configured - set clinicURL in config or use --clinic-url flag")
		return result
	}

	// Set clinic-specific headers (X-Deploy-Type, X-Provider, X-Region)
	setClinicHeaders(ctx)

	// Build time range (last 30 minutes)
	endTime := time.Now().Unix()
	beginTime := endTime - 1800 // 30 minutes ago

	// Build request URL with query parameters
	// /proxy/orgs/{orgID}/clusters/{clusterID}/pd/dashboard/api/statements/list
	baseURL := fmt.Sprintf("%s/proxy/orgs/%s/clusters/%s/pd/dashboard/api/statements/list",
		ctx.ClinicURL,
		ctx.OrgID,
		ctx.ClusterID,
	)

	params := url.Values{}
	params.Set("begin_time", fmt.Sprintf("%d", beginTime))
	params.Set("end_time", fmt.Sprintf("%d", endTime))
	params.Set("text", "")
	params.Set("fields", c.Fields)

	fullURL := fmt.Sprintf("%s?%s", baseURL, params.Encode())
	result.SetRequest("GET", fullURL, nil)

	// Send request
	resp, err := ctx.Client.Get(fullURL)
	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)
	// For clinic API: access-control-allow-origin is "*", access-control-allow-credentials can be absent
	checker := framework.NewCommonResponseChecker(result, ctx.Origin)
	if ctx.EnableNewPath {
		checker.CheckCORSHeaders(resp)
	} else {
		checker.CheckCORSHeadersWithOptions(resp, framework.CORSCheckOptions{
			ExpectedOrigin:      "*",
			CredentialsOptional: true,
		})
	}
	checker.CheckStatusCode(resp, 200)

	// 2. Parse response - should be an array of statement items
	var stmtList []StmtListItem
	if err := json.Unmarshal(resp.Body, &stmtList); err != nil {
		result.AddError(fmt.Sprintf("Failed to parse response as statement list: %v", err))
		return result
	}

	// 3. Verify the list is not empty
	if msg := assertions.ShouldBeGreaterThan(len(stmtList), 0); msg != "" {
		result.AddError(fmt.Sprintf("Statement list should not be empty: %s", msg))
		return result
	}

	return result
}
