package validation

import (
	"reflect"
	"testing"
)

type User struct {
	Name    string
	Age     int
	Address *Address
	Tags    []string
	License License
}

type Address struct {
	City    string
	Country string
}

type License struct {
	ID         string
	Categories []string
}

func TestFilterAllowedStructFields(t *testing.T) {
	tests := []struct {
		name           string
		input          interface{}
		existing       interface{}
		allowedFields  map[string]bool
		expectedResult interface{}
		expectError    bool
	}{
		{
			name: "Filter top-level fields",
			input: &User{
				Name: "Alice",
				Age:  30,
			},
			existing: &User{
				Name: "Bob",
				Age:  25,
			},
			allowedFields: map[string]bool{
				"Name": true,
			},
			expectedResult: &User{
				Name: "Alice", // Allowed field
				Age:  25,      // Kept from existing
			},
			expectError: false,
		},
		{
			name: "Filter nested struct fields",
			input: &User{
				Name: "Alice",
				Address: &Address{
					City:    "New York",
					Country: "USA",
				},
			},
			existing: &User{
				Name: "Bob",
				Address: &Address{
					City:    "London",
					Country: "UK",
				},
			},
			allowedFields: map[string]bool{
				"Address.City": true,
			},
			expectedResult: &User{
				Name: "Bob", // Kept from existing
				Address: &Address{
					City:    "New York", // Allowed field
					Country: "UK",       // Kept from existing
				},
			},
			expectError: false,
		},
		{
			name: "Filter slice fields",
			input: &User{
				Tags: []string{"admin", "user"},
			},
			existing: &User{
				Tags: []string{"guest"},
			},
			allowedFields: map[string]bool{
				"Tags": true,
			},
			expectedResult: &User{
				Tags: []string{"admin", "user"}, // Allowed slice
			},
			expectError: false,
		},
		{
			name: "Filter slice of structs",
			input: &User{
				License: License{
					ID:         "123",
					Categories: []string{"A", "B"},
				},
			},
			existing: &User{
				License: License{
					ID:         "456",
					Categories: []string{"C"},
				},
			},
			allowedFields: map[string]bool{
				"License.ID": true,
			},
			expectedResult: &User{
				License: License{
					ID:         "123",         // Allowed field
					Categories: []string{"C"}, // Kept from existing
				},
			},
			expectError: false,
		},
		{
			name: "Filter pointer fields",
			input: &User{
				Address: &Address{
					City: "Paris",
				},
			},
			existing: &User{
				Address: &Address{
					City:    "Berlin",
					Country: "Germany",
				},
			},
			allowedFields: map[string]bool{
				"Address.City": true,
			},
			expectedResult: &User{
				Address: &Address{
					City:    "Paris",   // Allowed field
					Country: "Germany", // Kept from existing
				},
			},
			expectError: false,
		},
		{
			name: "Invalid input (non-pointer)",
			input: User{
				Name: "Alice",
			},
			existing: &User{
				Name: "Bob",
			},
			allowedFields: map[string]bool{
				"Name": true,
			},
			expectedResult: nil,
			expectError:    true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := FilterAllowedStructFields(tt.input, tt.existing, tt.allowedFields, "")
			if (err != nil) != tt.expectError {
				t.Errorf("FilterAllowedStructFields() error = %v, expectError %v", err, tt.expectError)
				return
			}

			if !tt.expectError && !reflect.DeepEqual(tt.input, tt.expectedResult) {
				t.Errorf("FilterAllowedStructFields() = %+v, expected %+v", tt.input, tt.expectedResult)
			}
		})
	}
}
