package dedicated

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

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

// AlertsCase test case for alerts list API
type AlertsCase struct {
	limit int
	page  int
}

func NewAlertsCase() *AlertsCase {
	return &AlertsCase{
		limit: 20,
		page:  1,
	}
}

func (c *AlertsCase) Name() string {
	return "AlertsList"
}

func (c *AlertsCase) Description() string {
	return "Verify alerts list API - /api/v1/external/{bizType}/orgs/{orgID}/projects/{projectID}/clusters/{clusterID}/alerts"
}

// AlertsResponse response structure for alerts API
type AlertsResponse struct {
	Code    int        `json:"code"`
	Message string     `json:"message"`
	Data    AlertsData `json:"data"`
}

type AlertsData struct {
	Alerts []AlertItem `json:"alerts"`
	Total  int         `json:"total"`
}

type AlertItem struct {
	// Alert fields - define as needed, but we only need to verify it's a list
	ID        string `json:"id,omitempty"`
	Name      string `json:"name,omitempty"`
	Status    string `json:"status,omitempty"`
	StartTime int64  `json:"startTime,omitempty"`
	EndTime   int64  `json:"endTime,omitempty"`
}

func (c *AlertsCase) 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 time range: last 2 days
	endTime := time.Now().Unix()
	startTime := endTime - 2*24*60*60 // 2 days ago

	// Build request URL
	// /api/v1/external/{bizType}/orgs/{orgID}/projects/{projectID}/clusters/{clusterID}/alerts
	params := url.Values{}
	params.Set("region", region)
	params.Set("vendor", vendor)
	params.Set("startTime", strconv.FormatInt(startTime, 10))
	params.Set("endTime", strconv.FormatInt(endTime, 10))
	params.Set("limit", strconv.Itoa(c.limit))
	params.Set("page", strconv.Itoa(c.page))

	apiURL := fmt.Sprintf("%s/api/v1/external/%s/orgs/%s/projects/%s/clusters/%s/alerts?%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 AlertsResponse
	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 total >= 0
	if msg := assertions.ShouldBeGreaterThanOrEqualTo(respBody.Data.Total, 0); msg != "" {
		result.AddError(fmt.Sprintf("Total should be >= 0: %s", msg))
	}

	// 5. Verify alerts is a list (can be empty)
	// Since we parsed into []AlertItem, if parsing succeeded, it's a valid list
	// Just verify it's not nil (Go slice can be nil or empty, both are valid)
	if respBody.Data.Alerts == nil {
		// Initialize to empty slice if nil to ensure it's a list
		respBody.Data.Alerts = []AlertItem{}
	}

	return result
}
