package automation

import (
	"context"
	"errors"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestBootstrapFieldMappingApplier_CopiesRegistryRowsAndRespectsDefaults(t *testing.T) {
	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
	require.NoError(t, err)
	defer db.Close()

	mock.ExpectQuery(`SELECT Source, SourceField, TargetField, DefaultValue, SourceLookupField\s+FROM _System_ObjectFieldMapping`).
		WithArgs("Lead", "Contact", "convert").
		WillReturnRows(sqlmock.NewRows([]string{"Source", "SourceField", "TargetField", "DefaultValue", "SourceLookupField"}).
			AddRow("standard", "FirstName", "FirstName", nil, nil).
			AddRow("standard", "LastName", "LastName", nil, nil).
			AddRow("standard", "Email", "Email", "unknown@example.com", nil))

	applier := NewBootstrapFieldMappingApplier(db)

	source := map[string]interface{}{
		"FirstName": "Ada",
		"LastName":  "Lovelace",
	}
	target := map[string]interface{}{}

	require.NoError(t, applier.ApplyMappings(context.Background(), "Lead", "Contact", "convert", source, target))
	assert.Equal(t, "Ada", target["FirstName"])
	assert.Equal(t, "Lovelace", target["LastName"])
	assert.Equal(t, "unknown@example.com", target["Email"], "default must fill when source has no Email")
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestBootstrapFieldMappingApplier_PropagatesRegistryReadError(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	mock.ExpectQuery(`SELECT Source, SourceField, TargetField, DefaultValue, SourceLookupField FROM _System_ObjectFieldMapping`).
		WillReturnError(errors.New("registry unavailable"))

	applier := NewBootstrapFieldMappingApplier(db)

	err = applier.ApplyMappings(context.Background(), "Lead", "Contact", "convert",
		map[string]interface{}{}, map[string]interface{}{})
	require.Error(t, err)
	assert.Contains(t, err.Error(), "registry unavailable")
}

func TestBootstrapFieldMappingApplier_EmptyRegistryLeavesTargetUntouched(t *testing.T) {
	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
	require.NoError(t, err)
	defer db.Close()

	mock.ExpectQuery(`SELECT Source, SourceField, TargetField, DefaultValue, SourceLookupField\s+FROM _System_ObjectFieldMapping`).
		WithArgs("Lead", "Contact", "convert").
		WillReturnRows(sqlmock.NewRows([]string{"Source", "SourceField", "TargetField", "DefaultValue", "SourceLookupField"}))

	applier := NewBootstrapFieldMappingApplier(db)

	target := map[string]interface{}{"PreviouslySet": "keep"}
	require.NoError(t, applier.ApplyMappings(context.Background(), "Lead", "Contact", "convert",
		map[string]interface{}{"FirstName": "Ada"}, target))
	assert.Equal(t, "keep", target["PreviouslySet"])
	assert.NotContains(t, target, "FirstName")
	require.NoError(t, mock.ExpectationsWereMet())
}
