package automation

import (
	"testing"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/assert"
)

// ---------------------------------------------------------------------------
// recordToInterview
// ---------------------------------------------------------------------------

func TestRecordToInterview(t *testing.T) {
	tests := []struct {
		name     string
		record   models.SObject
		checkNil bool
		check    func(t *testing.T, interview *models.FlowInterview)
	}{
		{
			name:     "nil record returns nil",
			record:   nil,
			checkNil: true,
		},
		{
			name: "full record conversion",
			record: models.SObject{
				constants.FieldID: "int-001",
				"FlowVersionId":   "ver-001",
				"InterviewLabel":  "My Flow",
				"InterviewStatus": "Running",
				"CurrentElement":  "Decision_1",
				"OwnerId":         "user-001",
				"ContextData":     `{"counter":5}`,
			},
			check: func(t *testing.T, interview *models.FlowInterview) {
				assert.Equal(t, "int-001", interview.Id)
				assert.Equal(t, "ver-001", interview.FlowVersionId)
				assert.Equal(t, "My Flow", interview.InterviewLabel)
				assert.Equal(t, "Running", interview.InterviewStatus)
				assert.Equal(t, "Decision_1", interview.CurrentElement)
				assert.Equal(t, "user-001", interview.OwnerId)
				assert.NotNil(t, interview.ContextData)
				assert.Equal(t, float64(5), interview.ContextData["counter"])
			},
		},
		{
			name: "empty context data",
			record: models.SObject{
				constants.FieldID: "int-002",
				"ContextData":     "",
			},
			check: func(t *testing.T, interview *models.FlowInterview) {
				assert.Equal(t, "int-002", interview.Id)
				assert.Nil(t, interview.ContextData)
			},
		},
		{
			name: "missing optional fields",
			record: models.SObject{
				constants.FieldID: "int-003",
			},
			check: func(t *testing.T, interview *models.FlowInterview) {
				assert.Equal(t, "int-003", interview.Id)
				assert.Empty(t, interview.FlowVersionId)
				assert.Empty(t, interview.InterviewLabel)
			},
		},
		{
			name: "invalid context JSON is ignored",
			record: models.SObject{
				constants.FieldID: "int-004",
				"ContextData":     "{invalid-json",
			},
			check: func(t *testing.T, interview *models.FlowInterview) {
				assert.Equal(t, "int-004", interview.Id)
				assert.Nil(t, interview.ContextData)
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := recordToInterview(tt.record)
			if tt.checkNil {
				assert.Nil(t, result)
			} else {
				assert.NotNil(t, result)
				tt.check(t, result)
			}
		})
	}
}

// ---------------------------------------------------------------------------
// countFlowElements
// ---------------------------------------------------------------------------

func TestCountFlowElements(t *testing.T) {
	tests := []struct {
		name     string
		meta     *models.FlowMetadata
		expected int
	}{
		{
			name:     "nil metadata",
			meta:     nil,
			expected: 0,
		},
		{
			name:     "empty metadata",
			meta:     &models.FlowMetadata{},
			expected: 0,
		},
		{
			name: "counts all element types",
			meta: &models.FlowMetadata{
				Decisions:     []models.FlowDecision{{Name: "d1"}, {Name: "d2"}},
				Assignments:   []models.FlowAssignment{{Name: "a1"}},
				RecordCreates: []models.FlowRecordCreate{{Name: "c1"}},
				RecordUpdates: []models.FlowRecordUpdate{{Name: "u1"}},
				RecordDeletes: []models.FlowRecordDelete{{Name: "del1"}},
				RecordLookups: []models.FlowRecordLookup{{Name: "l1"}},
				ActionCalls:   []models.FlowActionCall{{Name: "ac1"}},
				Subflows:      []models.FlowSubflow{{Name: "sf1"}},
				Screens:       []models.FlowScreen{{Name: "sc1"}},
			},
			expected: 10,
		},
		{
			name: "only decisions",
			meta: &models.FlowMetadata{
				Decisions: []models.FlowDecision{{Name: "d1"}, {Name: "d2"}, {Name: "d3"}},
			},
			expected: 3,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := countFlowElements(tt.meta)
			assert.Equal(t, tt.expected, result)
		})
	}
}
