package triggerprojection

import (
	"encoding/json"
	"os/exec"
	"strings"
	"testing"

	"github.com/nexuscrm/shared/pkg/models"
)

func TestResolveTriggerOrder(t *testing.T) {
	tests := []struct {
		name    string
		version *models.FlowVersion
		wantNil bool
		wantVal int
	}{
		{
			name: "MetadataRaw with triggerOrder int",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"start":{"triggerType":"RecordAfterSave","object":"Account","triggerOrder":400}}`),
			},
			wantNil: false,
			wantVal: 400,
		},
		{
			name: "MetadataRaw with triggerOrder 0",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"start":{"triggerType":"RecordAfterSave","object":"Account","triggerOrder":0}}`),
			},
			wantNil: false,
			wantVal: 0,
		},
		{
			name: "MetadataRaw missing triggerOrder",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"start":{"triggerType":"RecordAfterSave","object":"Account"}}`),
			},
			wantNil: true,
		},
		{
			name: "MetadataRaw triggerOrder is string (malformed — silently ignored)",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"start":{"triggerType":"RecordAfterSave","object":"Account","triggerOrder":"bad"}}`),
			},
			wantNil: true,
		},
		{
			name: "MetadataRaw no start element",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"variables":[]}`),
			},
			wantNil: true,
		},
		{
			name:    "nil version",
			version: nil,
			wantNil: true,
		},
		{
			name:    "nil MetadataRaw",
			version: &models.FlowVersion{},
			wantNil: true,
		},
		{
			name: "MetadataRaw empty object",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{}`),
			},
			wantNil: true,
		},
		{
			name: "MetadataRaw with triggerOrder 500 via explicit JSON",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"start":{"triggerType":"RecordAfterSave","object":"Account","triggerOrder":500}}`),
			},
			wantNil: false,
			wantVal: 500,
		},
		{
			name: "MetadataRaw with triggerOrder 250",
			version: &models.FlowVersion{
				MetadataRaw: json.RawMessage(`{"start":{"triggerType":"RecordAfterSave","object":"Account","triggerOrder":250}}`),
			},
			wantNil: false,
			wantVal: 250,
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got := ResolveTriggerOrder(tc.version)
			if tc.wantNil {
				if got != nil {
					t.Errorf("ResolveTriggerOrder() = %d, want nil", *got)
				}
				return
			}
			if got == nil {
				t.Errorf("ResolveTriggerOrder() = nil, want %d", tc.wantVal)
				return
			}
			if *got != tc.wantVal {
				t.Errorf("ResolveTriggerOrder() = %d, want %d", *got, tc.wantVal)
			}
		})
	}
}

// TestTriggerOrderSingleResolver is a grep-guard test. It verifies that the
// only production code (outside this package and test files) that parses
// triggerOrder from JSON is the ResolveTriggerOrder helper.
func TestTriggerOrderSingleResolver(t *testing.T) {
	// Grep for "triggerOrder" in production Go files, excluding:
	// - this package (triggerprojection/*) — the owner
	// - *_test.go files
	cmd := exec.Command("sh", "-c",
		`cd "$(git -C . rev-parse --show-toplevel)" && `+
			`(command -v rg >/dev/null && rg --no-heading -n '"triggerOrder"' backend/ shared/ `+
			`--glob '!**/triggerprojection/**' --glob '!**/*_test.go' `+
			`|| grep -rn '"triggerOrder"' backend/ shared/ `+
			`--include='*.go' `+
			`--exclude-dir=triggerprojection `+
			`--exclude='*_test.go') 2>/dev/null || true`,
	)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Logf("grep command error (non-fatal): %v", err)
	}
	output := strings.TrimSpace(string(out))
	if output != "" {
		t.Errorf("found inline triggerOrder JSON parsing outside triggerprojection package:\n%s\n\nOnly ResolveTriggerOrder in triggerprojection should parse this field.", output)
	}
}
