package commerce

import (
	"context"
	"strings"
	"testing"
)

func TestZJMFStockProductAcceptsNestedResponseShapes(t *testing.T) {
	product := map[string]any{"id": 9, "stock_control": 1, "qty": 3}
	shapes := []map[string]any{
		product,
		{"product": product},
		{"products": product},
		{"data": map[string]any{"products": product}},
		{"data": map[string]any{"products": []any{product}}},
	}
	for index, shape := range shapes {
		got := zjmfStockProduct(shape)
		if got == nil || intValueAny(got["qty"], 0) != 3 {
			t.Fatalf("shape %d parsed as %#v", index, got)
		}
	}
	if got := zjmfStockProduct(map[string]any{"status": 200, "data": map[string]any{"message": "ok"}}); got != nil {
		t.Fatalf("malformed response parsed as product: %#v", got)
	}
}

func TestExtractRealDataItemsHandlesNestedLists(t *testing.T) {
	payload := map[string]any{"data": map[string]any{"list": []any{
		map[string]any{"id": 1, "cpu_usage": 12.5},
		map[string]any{"id": 2, "cpu_usage": 18.5},
	}}}
	items := extractRealDataItems(payload)
	if len(items) != 2 || intValueAny(items[1]["id"], 0) != 2 {
		t.Fatalf("items = %#v", items)
	}
}

func TestChartLastValuesUsesLastValidPointPerSeries(t *testing.T) {
	body := map[string]any{"data": map[string]any{"list": []any{
		[]any{map[string]any{"value": 1.5}, map[string]any{"value": "2.5"}},
		[]any{nil, map[string]any{"value": 7}},
	}}}
	values := chartLastValues(body)
	if len(values) != 2 || values[0] == nil || *values[0] != 2.5 || values[1] == nil || *values[1] != 7 {
		t.Fatalf("values = %#v", values)
	}
}

func TestAgentTierRankMatchesLegacyOrdering(t *testing.T) {
	current := AgentTier{MonthlySalesRequired: 10000, MonthlyActiveCustomersRequired: 10, MinTotalSpend: 1000, MinMemberLevel: 2, CostRate: 80, SortOrder: 1}
	lowerByCost := current
	lowerByCost.CostRate = 90
	if compareAgentTierRank(lowerByCost, current) >= 0 {
		t.Fatalf("higher cost rate should rank lower: %#v >= %#v", agentTierRank(lowerByCost), agentTierRank(current))
	}
	higherBySort := current
	higherBySort.SortOrder = 2
	if compareAgentTierRank(higherBySort, current) <= 0 {
		t.Fatalf("higher sort order should rank higher: %#v <= %#v", agentTierRank(higherBySort), agentTierRank(current))
	}
}

func TestDefaultTaskDefinitionsAreUnique(t *testing.T) {
	seen := map[string]struct{}{}
	for _, definition := range DefaultTaskDefinitions() {
		if definition.Key == "" || definition.Name == "" || definition.Description == "" {
			t.Fatalf("incomplete definition: %#v", definition)
		}
		if _, exists := seen[definition.Key]; exists {
			t.Fatalf("duplicate task key %q", definition.Key)
		}
		seen[definition.Key] = struct{}{}
	}
	for _, required := range []string{"provision", "settlement", "upstream_actions", "instance_lifecycle", "agent_lifecycle_evaluate", "zjmf_stock_sync", "promotion_coupon_refund_expired", "promotion_coupon_notify_expiring", "verification_material_cleanup", "instance_real_data_collect", "recharge_maintenance", "cloud_node_health"} {
		if _, exists := seen[required]; !exists {
			t.Fatalf("missing task definition %q", required)
		}
	}
}

type panicTaskExecutor struct{}

func (panicTaskExecutor) Definitions() []TaskDefinition { return nil }

func (panicTaskExecutor) Execute(context.Context, string) (map[string]any, error) {
	panic("boom")
}

func TestExecuteTaskSafelyConvertsPanicToError(t *testing.T) {
	if _, err := executeTaskSafely(context.Background(), panicTaskExecutor{}, "panic"); err == nil || !strings.Contains(err.Error(), "boom") {
		t.Fatalf("panic error = %v", err)
	}
}
