package automation

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
)

// TestCriteriaItemValueHandling tests the specific issue of distinguishing between
// null and empty string values in criteria items
func TestCriteriaItemValueHandling(t *testing.T) {
	t.Parallel()

	t.Run("null value in JSON produces invalid nullableString", func(t *testing.T) {
		jsonData := `{"field": "Amount", "operation": "greaterThan", "value": null}`
		var item criteriaItemJSON
		err := json.Unmarshal([]byte(jsonData), &item)
		assert.NoError(t, err)
		assert.False(t, item.Value.Valid)
		assert.Equal(t, "", item.Value.String)
	})

	t.Run("empty string value in JSON produces valid nullableString with empty string", func(t *testing.T) {
		jsonData := `{"field": "Name", "operation": "equals", "value": ""}`
		var item criteriaItemJSON
		err := json.Unmarshal([]byte(jsonData), &item)
		assert.NoError(t, err)
		assert.True(t, item.Value.Valid)
		assert.Equal(t, "", item.Value.String)
	})

	t.Run("non-empty string value in JSON produces valid nullableString", func(t *testing.T) {
		jsonData := `{"field": "Name", "operation": "equals", "value": "test"}`
		var item criteriaItemJSON
		err := json.Unmarshal([]byte(jsonData), &item)
		assert.NoError(t, err)
		assert.True(t, item.Value.Valid)
		assert.Equal(t, "test", item.Value.String)
	})

	t.Run("normalization with null value produces empty string", func(t *testing.T) {
		jsonData := `{"criteriaItems": [{"field": "Amount", "operation": "greaterThan", "value": null}]}`
		var criteria criteriaJSON
		err := json.Unmarshal([]byte(jsonData), &criteria)
		assert.NoError(t, err)

		normalized := normalizeCriteriaJSON(&criteria)
		assert.Len(t, normalized.CriteriaItems, 1)
		assert.Equal(t, "", normalized.CriteriaItems[0].Value) // null should become empty string
		assert.Equal(t, "Amount", normalized.CriteriaItems[0].Field)
		assert.Equal(t, "greaterThan", normalized.CriteriaItems[0].Operation)
	})

	t.Run("normalization with empty string preserves empty string", func(t *testing.T) {
		jsonData := `{"criteriaItems": [{"field": "Name", "operation": "equals", "value": ""}]}`
		var criteria criteriaJSON
		err := json.Unmarshal([]byte(jsonData), &criteria)
		assert.NoError(t, err)

		normalized := normalizeCriteriaJSON(&criteria)
		assert.Len(t, normalized.CriteriaItems, 1)
		assert.Equal(t, "", normalized.CriteriaItems[0].Value) // empty string preserved
		assert.Equal(t, "Name", normalized.CriteriaItems[0].Field)
		assert.Equal(t, "equals", normalized.CriteriaItems[0].Operation)
	})

	t.Run("normalization with non-empty string preserves value", func(t *testing.T) {
		jsonData := `{"criteriaItems": [{"field": "Name", "operation": "equals", "value": "John"}]}`
		var criteria criteriaJSON
		err := json.Unmarshal([]byte(jsonData), &criteria)
		assert.NoError(t, err)

		normalized := normalizeCriteriaJSON(&criteria)
		assert.Len(t, normalized.CriteriaItems, 1)
		assert.Equal(t, "John", normalized.CriteriaItems[0].Value)
		assert.Equal(t, "Name", normalized.CriteriaItems[0].Field)
		assert.Equal(t, "equals", normalized.CriteriaItems[0].Operation)
	})
}