package dedicated

import (
	"encoding/json"
	"fmt"

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

// SharedDataKey constants for new path shared data keys
const (
	KeyNewPathMetricsOpenReadUri       = "newPathMetricsOpenReadUri"
	KeyNewPathSlowQueryOpenReadUri     = "newPathSlowQueryOpenReadUri"
	KeyNewPathKeyVisualOpenReadUri     = "newPathKeyVisualOpenReadUri"
	KeyNewPathSQLStatementsOpenReadUri = "newPathSqlStatementsOpenReadUri"
)

// GetClusterRouteNewPathCase test case for getting cluster route information using new API path
type GetClusterRouteNewPathCase struct{}

// NewGetClusterRouteNewPathCase creates a new GetClusterRouteNewPathCase instance
func NewGetClusterRouteNewPathCase() *GetClusterRouteNewPathCase {
	return &GetClusterRouteNewPathCase{}
}

func (c *GetClusterRouteNewPathCase) Name() string {
	return "GetClusterRouteNewPath"
}

func (c *GetClusterRouteNewPathCase) Description() string {
	return "Verify get cluster route API (gateway) - /api/v1/external/{bizType}/orgs/{orgID}/projects/{projectID}/clusters/{clusterID}/"
}

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

	// Build request URL with gateway URL (same path as old, different base URL)
	// /api/v1/external/{bizType}/orgs/{orgID}/projects/{projectID}/clusters/{clusterID}/
	url := fmt.Sprintf("%s/api/v1/external/%s/orgs/%s/projects/%s/clusters/%s/?canary=true",
		ctx.O11yGatewayURL,
		ctx.BizType,
		ctx.OrgID,
		ctx.ProjectID,
		ctx.ClusterID,
	)
	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 ClusterRouteResponse
	if err := json.Unmarshal(resp.Body, &respBody); err != nil {
		result.AddError(fmt.Sprintf("Failed to parse response JSON: %v", err))
		return result
	}

	// 3. Verify code is 0
	if msg := assertions.ShouldEqual(respBody.Code, 0); msg != "" {
		result.AddError(fmt.Sprintf("Response code should be 0: %s", msg))
	}

	// 4. Verify applicationID matches clusterID
	if msg := assertions.ShouldEqual(respBody.Data.ApplicationID, ctx.ClusterID); msg != "" {
		result.AddError(fmt.Sprintf("applicationID should match clusterID: %s", msg))
	}

	// 5. Verify projectID matches
	if msg := assertions.ShouldEqual(respBody.Data.ProjectID, ctx.ProjectID); msg != "" {
		result.AddError(fmt.Sprintf("projectID should match: %s", msg))
	}

	// 6. Verify tenantID matches orgID
	if msg := assertions.ShouldEqual(respBody.Data.TenantID, ctx.OrgID); msg != "" {
		result.AddError(fmt.Sprintf("tenantID should match orgID: %s", msg))
	}

	// 7. Verify keyVisual.openReadUri is not empty
	if msg := assertions.ShouldNotBeEmpty(respBody.Data.KeyVisual.OpenReadUri); msg != "" {
		result.AddError(fmt.Sprintf("keyVisual.openReadUri should not be empty: %s", msg))
	}

	// 8. Verify metrics.openReadUri is not empty
	if msg := assertions.ShouldNotBeEmpty(respBody.Data.Metrics.OpenReadUri); msg != "" {
		result.AddError(fmt.Sprintf("metrics.openReadUri should not be empty: %s", msg))
	}

	// 9. Verify slowQuery.openReadUri is not empty
	if msg := assertions.ShouldNotBeEmpty(respBody.Data.SlowQuery.OpenReadUri); msg != "" {
		result.AddError(fmt.Sprintf("slowQuery.openReadUri should not be empty: %s", msg))
	}

	// Store openReadUri values in shared data for dependent cases (with newPath prefix)
	ctx.SetSharedData(KeyNewPathMetricsOpenReadUri, respBody.Data.Metrics.OpenReadUri)
	ctx.SetSharedData(KeyNewPathSlowQueryOpenReadUri, respBody.Data.SlowQuery.OpenReadUri)
	ctx.SetSharedData(KeyNewPathKeyVisualOpenReadUri, respBody.Data.KeyVisual.OpenReadUri)
	ctx.SetSharedData(KeyNewPathSQLStatementsOpenReadUri, respBody.Data.SQLStatements.OpenReadUri)

	return result
}
