package commerce

import (
	"testing"
	"time"
)

func TestUpstreamActionLogResponseDecodesJSONPayloads(t *testing.T) {
	now := time.Date(2026, 7, 9, 12, 0, 0, 0, time.UTC)
	userID := int64(10)
	instanceID := int64(20)
	item := UpstreamActionLog{
		ID:              1,
		UserID:          &userID,
		InstanceID:      &instanceID,
		ActionType:      "power-on",
		ResourceType:    "instance",
		Source:          "user",
		Status:          "failed",
		RequestPayload:  jsonRawFromAny(map[string]any{"a": "b"}),
		ResponsePayload: jsonRawFromAny(map[string]any{"ok": false}),
		TaskPayload:     jsonRawFromAny([]any{"task"}),
		CreatedAt:       now,
		UpdatedAt:       now,
	}
	got := newUpstreamActionLogResponse(item)
	if got.ID != 1 || got.UserID == nil || *got.UserID != userID || got.InstanceID == nil || *got.InstanceID != instanceID {
		t.Fatalf("basic fields = %#v", got)
	}
	if payload, ok := got.RequestPayload.(map[string]any); !ok || payload["a"] != "b" {
		t.Fatalf("request payload = %#v", got.RequestPayload)
	}
	if payload, ok := got.ResponsePayload.(map[string]any); !ok || payload["ok"] != false {
		t.Fatalf("response payload = %#v", got.ResponsePayload)
	}
	if payload, ok := got.TaskPayload.([]any); !ok || len(payload) != 1 || payload[0] != "task" {
		t.Fatalf("task payload = %#v", got.TaskPayload)
	}
}

func TestPluginActionManifestGuards(t *testing.T) {
	manifest := map[string]any{
		"manage_actions": []any{
			map[string]any{"key": "sync"},
			map[string]any{"key": "terminate", "audience": "admin"},
		},
	}
	if !pluginActionAllowed(manifest, "sync") {
		t.Fatal("sync should be allowed")
	}
	if pluginActionAudience(manifest, "sync") != "both" {
		t.Fatalf("sync audience = %q", pluginActionAudience(manifest, "sync"))
	}
	if pluginActionAudience(manifest, "terminate") != "admin" {
		t.Fatalf("terminate audience = %q", pluginActionAudience(manifest, "terminate"))
	}
	if pluginActionAllowed(manifest, "missing") {
		t.Fatal("missing action should not be allowed")
	}
}

func TestSanitizePluginManageResultMasksSecrets(t *testing.T) {
	got := sanitizePluginManageResult(map[string]any{
		"success":       true,
		"root_password": "top-secret",
		"payload": map[string]any{
			"root_password": "secret",
			"url":           "/control/server/1",
		},
	})
	payload := got["payload"].(map[string]any)
	if payload["root_password"] != "***" {
		t.Fatalf("root_password = %#v", payload["root_password"])
	}
	if payload["url"] != "/control/server/1" {
		t.Fatalf("url = %#v", payload["url"])
	}
	if got["root_password"] != "***" {
		t.Fatalf("top-level root_password = %#v", got["root_password"])
	}
}

func TestResolveUpstreamTaskStatus(t *testing.T) {
	cases := []struct {
		name string
		task map[string]any
		want string
	}{
		{name: "string success", task: map[string]any{"status": "completed"}, want: "success"},
		{name: "string failed", task: map[string]any{"status": "error"}, want: "failed"},
		{name: "numeric success", task: map[string]any{"status": float64(2)}, want: "success"},
		{name: "numeric failed", task: map[string]any{"status": float64(5)}, want: "failed"},
		{name: "progress success", task: map[string]any{"progress": float64(100)}, want: "success"},
		{name: "default running", task: map[string]any{"status": float64(1)}, want: "running"},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := resolveUpstreamTaskStatus(tc.task); got != tc.want {
				t.Fatalf("status = %q, want %q", got, tc.want)
			}
		})
	}
}

func TestSummarizeResourceStatus(t *testing.T) {
	if got := summarizeResourceStatus(nil); got != "none" {
		t.Fatalf("empty summary = %q", got)
	}
	if got := summarizeResourceStatus([]UpstreamActionLog{{Status: "submitted"}}); got != "running" {
		t.Fatalf("running summary = %q", got)
	}
	if got := summarizeResourceStatus([]UpstreamActionLog{{Status: "success"}}); got != "finished" {
		t.Fatalf("finished summary = %q", got)
	}
	if got := summarizeResourceStatus([]UpstreamActionLog{{Status: "success"}, {Status: "failed"}}); got != "failed" {
		t.Fatalf("failed summary = %q", got)
	}
}

func TestPluginManageResultOutcomeRejectsUnqueryableAsyncTask(t *testing.T) {
	taskID, message := pluginManageResultOutcome(map[string]any{"task_id": 42, "status": "running"})
	if taskID == nil || *taskID != 42 || message == "" {
		t.Fatalf("outcome = task=%v message=%q", taskID, message)
	}
	if taskID, message = pluginManageResultOutcome(map[string]any{"task_id": 42, "success": true}); taskID == nil || message != "" {
		t.Fatalf("terminal outcome = task=%v message=%q", taskID, message)
	}
}

func TestCanonicalPluginActionType(t *testing.T) {
	orderID := int64(9)
	cases := map[string]string{
		canonicalPluginActionType("renew", "renewal", &orderID):    "instance_renew",
		canonicalPluginActionType("terminate", "refund", &orderID): "instance_delete",
		canonicalPluginActionType("suspend", "lifecycle", nil):     "instance_suspend",
		canonicalPluginActionType("upgrade", "user", &orderID):     "upgrade",
		canonicalPluginActionType("open-panel", "user", nil):       "plugin_open-panel",
	}
	for got, want := range cases {
		if got != want {
			t.Fatalf("action type = %q, want %q", got, want)
		}
	}
}
