package persistence

import (
	"testing"

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

// MockScannable implements Scannable for testing argument counts
type MockScannable struct {
	CapturedArgs []interface{}
}

func (m *MockScannable) Scan(dest ...interface{}) error {
	m.CapturedArgs = dest
	// Return nil to simulate success, or handling it doesn't matter for count check
	// unless the scanner logic depends on values.
	// For scanFlow, it might panic if we pass nils?
	// Actually, scanFlow passes addresses (&var) to Scan.
	// We just capture them.
	// But subsequent logic (e.g. valid checks) might crash if we don't populate them.
	// Let's rely on the fact that Scan is the first thing called.
	// If the code panics *after* Scan because we didn't populate values, that's fine,
	// as long as we captured the count.
	return nil
}

func TestScannerParity(t *testing.T) {
	repo := &MetadataRepository{} // No DB needed for this check

	tests := []struct {
		Name          string
		Cols          []string
		ScanFunc      func(*MockScannable)
		ExpectedCount int
	}{
		{
			Name: "Object",
			Cols: constants.ColsSystemObject,
			ScanFunc: func(m *MockScannable) {
				repo.scanObject(m)
			},
		},
		{
			Name: "Field",
			Cols: constants.ColsSystemField,
			ScanFunc: func(m *MockScannable) {
				repo.scanField(m)
			},
		},
		{
			Name: "Action",
			Cols: constants.ColsSystemAction,
			ScanFunc: func(m *MockScannable) {
				repo.scanAction(m)
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.Name, func(t *testing.T) {
			mock := &MockScannable{}
			// Handle potential panic if code assumes specific data
			defer func() {
				if r := recover(); r != nil {
					// Even if it panics, we check if Scan was called with correct count
					if len(mock.CapturedArgs) != len(tt.Cols) {
						t.Errorf("Panic occurred, and Argument mismatch: Expected %d, got %d", len(tt.Cols), len(mock.CapturedArgs))
					}
				}
			}()

			tt.ScanFunc(mock)

			// Assertion
			assert.Equal(t, len(tt.Cols), len(mock.CapturedArgs), "Scanner argument count must match Columns constant count")
		})
	}
}
