package models

import (
	"testing"

	"github.com/nexuscrm/shared/pkg/constants"
)

func fieldsFixture() *ObjectMetadata {
	physical := FieldMetadata{APIName: "Name", Type: constants.FieldTypeString}
	virtualA := FieldMetadata{
		APIName:              "PermissionsViewSetup",
		Type:                 constants.FieldTypeBoolean,
		IsVirtual:            true,
		VirtualKind:          constants.VirtualFieldSystemPermission,
		VirtualSourceAPIName: "ViewSetup",
	}
	virtualB := FieldMetadata{
		APIName:              "PermissionsModifyAllData",
		Type:                 constants.FieldTypeBoolean,
		IsVirtual:            true,
		VirtualKind:          constants.VirtualFieldSystemPermission,
		VirtualSourceAPIName: "ModifyAllData",
	}
	m := &ObjectMetadata{
		APIName: "PermissionSet",
		Fields:  []FieldMetadata{physical, virtualA, virtualB},
	}
	m.FieldsMap = map[string]*FieldMetadata{
		"name":                     &m.Fields[0],
		"permissionsviewsetup":     &m.Fields[1],
		"permissionsmodifyalldata": &m.Fields[2],
	}
	return m
}

func TestLogicalFields_ReturnsEveryField(t *testing.T) {
	got := LogicalFields(fieldsFixture())
	if len(got) != 3 {
		t.Fatalf("LogicalFields: want 3 entries, got %d", len(got))
	}
}

func TestPersistableFields_ExcludesVirtuals(t *testing.T) {
	got := PersistableFields(fieldsFixture())
	if len(got) != 1 {
		t.Fatalf("PersistableFields: want 1 physical entry, got %d (%v)", len(got), got)
	}
	if got[0].APIName != "Name" {
		t.Fatalf("PersistableFields: want Name, got %s", got[0].APIName)
	}
}

func TestFindField_CaseInsensitive(t *testing.T) {
	schema := fieldsFixture()
	for _, candidate := range []string{"PermissionsViewSetup", "permissionsviewsetup", "PERMISSIONSVIEWSETUP"} {
		f := FindField(schema, candidate)
		if f == nil {
			t.Fatalf("FindField(%q): nil", candidate)
		}
		if f.VirtualSourceAPIName != "ViewSetup" {
			t.Fatalf("FindField(%q): want source ViewSetup, got %s", candidate, f.VirtualSourceAPIName)
		}
	}
}

func TestFindField_FallsBackWhenFieldsMapEmpty(t *testing.T) {
	schema := fieldsFixture()
	schema.FieldsMap = nil
	f := FindField(schema, "permissionsviewsetup")
	if f == nil || f.APIName != "PermissionsViewSetup" {
		t.Fatalf("FindField fallback failed: %+v", f)
	}
}

func TestVirtualFieldsByKind_FiltersByKind(t *testing.T) {
	got := VirtualFieldsByKind(fieldsFixture(), constants.VirtualFieldSystemPermission)
	if len(got) != 2 {
		t.Fatalf("VirtualFieldsByKind: want 2, got %d", len(got))
	}
	got = VirtualFieldsByKind(fieldsFixture(), "NonExistentKind")
	if len(got) != 0 {
		t.Fatalf("VirtualFieldsByKind(unknown kind): want empty, got %d", len(got))
	}
}

func TestHelpers_NilSafe(t *testing.T) {
	if LogicalFields(nil) != nil {
		t.Fatal("LogicalFields(nil) should return nil")
	}
	if PersistableFields(nil) != nil {
		t.Fatal("PersistableFields(nil) should return nil")
	}
	if FindField(nil, "anything") != nil {
		t.Fatal("FindField(nil, …) should return nil")
	}
	if VirtualFieldsByKind(nil, constants.VirtualFieldSystemPermission) != nil {
		t.Fatal("VirtualFieldsByKind(nil, …) should return nil")
	}
}
