package dedicated

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

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

// MonitorAlertRulesCase test case for monitor alert rules API
type MonitorAlertRulesCase struct{}

func NewMonitorAlertRulesCase() *MonitorAlertRulesCase {
	return &MonitorAlertRulesCase{}
}

func (c *MonitorAlertRulesCase) Name() string {
	return "MonitorAlertRules"
}

func (c *MonitorAlertRulesCase) Description() string {
	return "Verify monitor alert rules API - /api/v1/external/{bizType}/orgs/{orgID}/projects/{projectID}/clusters/{clusterID}/monitor-alertrules"
}

// MonitorAlertRulesResponse response structure for monitor alert rules API
type MonitorAlertRulesResponse struct {
	Code    int                    `json:"code"`
	Message string                 `json:"message,omitempty"`
	Data    map[string]interface{} `json:"data"`
}

// AlertRuleItem represents a single alert rule
type AlertRuleItem struct {
	Alert            string  `json:"alert"`
	AlertRuleID      string  `json:"alertRuleID"`
	CanEdit          string  `json:"canEdit"`
	DefaultFor       int     `json:"defaultFor"`
	DefaultThreshold float64 `json:"defaultThreshold"`
	For              int     `json:"for"`
	MonitorTarget    string  `json:"monitorTarget"`
	Operator         string  `json:"operator"`
	SortID           int     `json:"sortID"`
	Status           string  `json:"status"`
	Threshold        float64 `json:"threshold"`
}

// AlertRuleGroup represents a group of alert rules
type AlertRuleGroup struct {
	Name  string          `json:"name"`
	Rules []AlertRuleItem `json:"rules"`
}

// AlertRuleListData represents the data structure containing alert rule list
type AlertRuleListData struct {
	AlertRuleList []AlertRuleGroup `json:"alertRuleList"`
}

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

	// Parse regionID to get vendor and region
	// regionID format: "aws-us-east-1" -> vendor="aws", region="us-east-1"
	vendor := ""
	region := ""
	if len(ctx.RegionID) > 0 {
		// Find first dash position
		for i, ch := range ctx.RegionID {
			if ch == '-' {
				vendor = ctx.RegionID[:i]
				region = ctx.RegionID[i+1:]
				break
			}
		}
	}

	// Build request URL
	// /api/v1/external/{bizType}/orgs/{orgID}/projects/{projectID}/clusters/{clusterID}/monitor-alertrules
	params := url.Values{}
	params.Set("region", region)
	params.Set("vendor", vendor)

	apiURL := fmt.Sprintf("%s/api/v1/external/%s/orgs/%s/projects/%s/clusters/%s/monitor-alertrules?%s",
		ctx.O11yGSURL,
		ctx.BizType,
		ctx.OrgID,
		ctx.ProjectID,
		ctx.ClusterID,
		params.Encode(),
	)
	result.SetRequest("GET", apiURL, nil)

	// Send request
	resp, err := ctx.Client.Get(apiURL)
	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) - use strict mode
	checker := framework.NewCommonResponseChecker(result, ctx.Origin)
	checker.CheckCORSHeaders(resp)
	checker.CheckStatusCode(resp, 200)

	// 2. Parse response body
	var respBody MonitorAlertRulesResponse
	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 data is not nil (can be empty object {})
	if respBody.Data == nil {
		result.AddError("Response data should not be nil")
	}

	// 5. Parse the detailed alert rules and store in SharedData for dependent cases
	// Re-parse to get the typed structure
	type typedResponse struct {
		Code    int               `json:"code"`
		Message string            `json:"message,omitempty"`
		Data    AlertRuleListData `json:"data"`
	}
	var typedRespBody typedResponse
	if err := json.Unmarshal(resp.Body, &typedRespBody); err == nil {
		// Find customer/resources:45 rule and store its 'for' value
		for _, group := range typedRespBody.Data.AlertRuleList {
			for _, rule := range group.Rules {
				if rule.AlertRuleID == "customer/resources:45" {
					ctx.SetSharedData("alertrule_resources_45_for", rule.For)
					ctx.SetSharedData("alertrule_resources_45_threshold", rule.Threshold)
					break
				}
			}
		}
	}

	return result
}
