/**
 * SchemaFieldRenderer Tests
 *
 * Tests the field factory component that routes to specific field components
 * based on schema field type, handles conditional visibility, and manages
 * dynamic option fetching.
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import { SchemaFieldRenderer } from './SchemaFieldRenderer';
import { ActionField, Action } from '../../types/action';
import { AvailableContext } from '../../hooks/useAvailableContext';

// Mock all field components
vi.mock('./StringField', () => ({
  StringField: ({
    fieldName,
    field,
    value,
  }: {
    fieldName: string;
    field: { label?: string };
    value: string;
  }) => (
    <div data-testid="string-field" data-field-name={fieldName} data-value={value}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./NumberField', () => ({
  NumberField: ({ fieldName, field }: { fieldName: string; field: { label?: string } }) => (
    <div data-testid="number-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./BooleanField', () => ({
  BooleanField: ({ fieldName, field }: { fieldName: string; field: { label?: string } }) => (
    <div data-testid="boolean-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./SelectField', () => ({
  SelectField: ({ fieldName, field }: { fieldName: string; field: { label?: string } }) => (
    <div data-testid="select-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./DynamicSelectField', () => ({
  DynamicSelectField: ({
    fieldName,
    field,
    isLoading,
    dependencyMet,
    options,
  }: {
    fieldName: string;
    field: { label?: string };
    isLoading: boolean;
    dependencyMet: boolean;
    options: Array<{ value: string; label: string }>;
  }) => (
    <div
      data-testid="dynamic-select-field"
      data-field-name={fieldName}
      data-loading={isLoading}
      data-dependency-met={dependencyMet}
      data-options-count={options.length}
    >
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./KeyValueField', () => ({
  KeyValueField: ({
    fieldName,
    field,
    dependencyMet,
    isLoading,
  }: {
    fieldName: string;
    field: { label?: string };
    dependencyMet: boolean;
    isLoading: boolean;
  }) => (
    <div
      data-testid="key-value-field"
      data-field-name={fieldName}
      data-dependency-met={dependencyMet}
      data-loading={isLoading}
    >
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./RepeatableFieldGroup', () => ({
  RepeatableFieldGroup: ({
    fieldName,
    field,
  }: {
    fieldName: string;
    field: { label?: string };
  }) => (
    <div data-testid="repeatable-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./FilterGroupFieldComponent', () => ({
  FilterGroupFieldComponent: ({
    fieldName,
    field,
  }: {
    fieldName: string;
    field: { label?: string };
  }) => (
    <div data-testid="filter-group-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./DateField', () => ({
  DateField: ({ fieldName, field }: { fieldName: string; field: { label?: string } }) => (
    <div data-testid="date-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./RichTextField', () => ({
  RichTextField: ({ fieldName, field }: { fieldName: string; field: { label?: string } }) => (
    <div data-testid="richtext-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./ButtonGroupField', () => ({
  ButtonGroupField: ({ fieldName, field }: { fieldName: string; field: { label?: string } }) => (
    <div data-testid="button-group-field" data-field-name={fieldName}>
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('./MultiSelectField', () => ({
  MultiSelectField: ({
    fieldName,
    field,
    isLoading,
    dependencyMet,
    options,
  }: {
    fieldName: string;
    field: { label?: string };
    isLoading?: boolean;
    dependencyMet?: boolean;
    options?: Array<{ value: string; label: string }>;
  }) => (
    <div
      data-testid="multi-select-field"
      data-field-name={fieldName}
      data-loading={isLoading ?? false}
      data-dependency-met={dependencyMet ?? true}
      data-options-count={options?.length ?? 0}
    >
      {field.label || fieldName}
    </div>
  ),
}));

vi.mock('../CombinedSelectorField', () => ({
  CombinedSelectorField: ({
    selectorFieldName,
    targetFieldName,
    isLoading,
    dependencyMet,
    options,
  }: {
    selectorFieldName: string;
    targetFieldName: string;
    isLoading: boolean;
    dependencyMet: boolean;
    options: Array<{ value: string; label: string }>;
  }) => (
    <div
      data-testid="combined-selector-field"
      data-selector-name={selectorFieldName}
      data-target-name={targetFieldName}
      data-loading={isLoading}
      data-dependency-met={dependencyMet}
      data-options-count={options.length}
    >
      Combined Selector
    </div>
  ),
}));

describe('SchemaFieldRenderer', () => {
  const mockOnChange = vi.fn();
  const mockOnQueueFetch = vi.fn();

  const mockAvailableContext: AvailableContext = {
    groups: [
      {
        namespace: 'Trigger',
        sourceName: 'User Registration',
        sourceType: 'trigger',
        variables: [
          {
            path: 'Trigger.user_email',
            label: 'User Email',
            source: 'User Registration',
            namespace: 'Trigger',
            type: 'string',
            description: 'User email address',
            example: 'user@example.com',
          },
        ],
      },
    ],
  };

  const defaultProps = {
    onChange: mockOnChange,
    availableContext: mockAvailableContext,
    dynamicOptions: {},
    loadingDynamicFields: {},
    dynamicFieldErrors: {},
    onQueueFetch: mockOnQueueFetch,
    actionConfig: {},
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  // ==========================================================================
  // Field Type Routing Tests
  // ==========================================================================

  describe('field type routing', () => {
    it('renders StringField for string type', () => {
      const field: ActionField = {
        type: 'string',
        label: 'Email',
        description: '',
        required: false,
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="email"
          field={field}
          value="test@example.com"
        />,
      );
      expect(screen.getByTestId('string-field')).toBeInTheDocument();
      expect(screen.getByTestId('string-field')).toHaveAttribute('data-field-name', 'email');
    });

    it('renders StringField for text type', () => {
      const field: ActionField = {
        type: 'text',
        label: 'Description',
        description: '',
        required: false,
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="description"
          field={field}
          value="Some text"
        />,
      );
      expect(screen.getByTestId('string-field')).toBeInTheDocument();
    });

    it('renders NumberField for number type', () => {
      const field: ActionField = {
        type: 'number',
        label: 'Quantity',
        description: '',
        required: false,
      };
      render(
        <SchemaFieldRenderer {...defaultProps} fieldName="quantity" field={field} value={10} />,
      );
      expect(screen.getByTestId('number-field')).toBeInTheDocument();
      expect(screen.getByTestId('number-field')).toHaveAttribute('data-field-name', 'quantity');
    });

    it('renders BooleanField for boolean type', () => {
      const field: ActionField = {
        type: 'boolean',
        label: 'Active',
        description: '',
        required: false,
      };
      render(
        <SchemaFieldRenderer {...defaultProps} fieldName="is_active" field={field} value={true} />,
      );
      expect(screen.getByTestId('boolean-field')).toBeInTheDocument();
      expect(screen.getByTestId('boolean-field')).toHaveAttribute('data-field-name', 'is_active');
    });

    it('renders SelectField for static select type', () => {
      const field: ActionField = {
        type: 'select',
        label: 'Status',
        description: '',
        required: false,
        options: [
          { value: 'active', label: 'Active' },
          { value: 'inactive', label: 'Inactive' },
        ],
      };
      render(
        <SchemaFieldRenderer {...defaultProps} fieldName="status" field={field} value="active" />,
      );
      expect(screen.getByTestId('select-field')).toBeInTheDocument();
      expect(screen.getByTestId('select-field')).toHaveAttribute('data-field-name', 'status');
    });

    it('renders DynamicSelectField for dynamic select type', () => {
      const field: ActionField = {
        type: 'select',
        label: 'List',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/lists',
      };
      render(<SchemaFieldRenderer {...defaultProps} fieldName="list_id" field={field} value="" />);
      expect(screen.getByTestId('dynamic-select-field')).toBeInTheDocument();
      expect(screen.getByTestId('dynamic-select-field')).toHaveAttribute(
        'data-field-name',
        'list_id',
      );
    });

    it('renders KeyValueField for key_value type', () => {
      const field: ActionField = {
        type: 'key_value',
        label: 'Custom Fields',
        description: '',
        required: false,
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="custom_fields"
          field={field}
          value={{}}
        />,
      );
      expect(screen.getByTestId('key-value-field')).toBeInTheDocument();
      expect(screen.getByTestId('key-value-field')).toHaveAttribute(
        'data-field-name',
        'custom_fields',
      );
    });

    it('renders RepeatableFieldGroup for repeatable type', () => {
      const field: ActionField = {
        type: 'repeatable',
        label: 'Recipients',
        description: '',
        required: false,
        item_schema: {
          email: { type: 'string', label: 'Email', description: '', required: false },
        },
      };
      render(
        <SchemaFieldRenderer {...defaultProps} fieldName="recipients" field={field} value={[]} />,
      );
      expect(screen.getByTestId('repeatable-field')).toBeInTheDocument();
      expect(screen.getByTestId('repeatable-field')).toHaveAttribute(
        'data-field-name',
        'recipients',
      );
    });

    it('renders FilterGroupFieldComponent for filter_group type', () => {
      const field: ActionField = {
        type: 'filter_group',
        label: 'Filters',
        description: '',
        required: false,
        filter_config: {
          operators: ['and', 'or'],
          condition_mappings: {},
        },
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="filters"
          field={field}
          value={undefined}
        />,
      );
      expect(screen.getByTestId('filter-group-field')).toBeInTheDocument();
      expect(screen.getByTestId('filter-group-field')).toHaveAttribute(
        'data-field-name',
        'filters',
      );
    });

    it('renders RichTextField for richtext type', () => {
      const field: ActionField = {
        type: 'richtext',
        label: 'Email Body',
        description: 'HTML content',
        required: false,
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="body"
          field={field}
          value="<p>Hello</p>"
        />,
      );
      expect(screen.getByTestId('richtext-field')).toBeInTheDocument();
      expect(screen.getByTestId('richtext-field')).toHaveAttribute('data-field-name', 'body');
    });

    it('renders ButtonGroupField for button_group type', () => {
      const field: ActionField = {
        type: 'button_group',
        label: 'Format',
        description: 'Output format',
        required: false,
        options: [
          { value: 'html', label: 'HTML' },
          { value: 'text', label: 'Text' },
        ],
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="format"
          field={field}
          value="html"
        />,
      );
      expect(screen.getByTestId('button-group-field')).toBeInTheDocument();
      expect(screen.getByTestId('button-group-field')).toHaveAttribute('data-field-name', 'format');
    });

    it('renders MultiSelectField for static multi_select type', () => {
      const field: ActionField = {
        type: 'multi_select',
        label: 'Tags',
        description: 'Select tags',
        required: false,
        options: [
          { value: 'tag1', label: 'Tag 1' },
          { value: 'tag2', label: 'Tag 2' },
        ],
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="tags"
          field={field}
          value={['tag1']}
        />,
      );
      expect(screen.getByTestId('multi-select-field')).toBeInTheDocument();
      expect(screen.getByTestId('multi-select-field')).toHaveAttribute('data-field-name', 'tags');
    });

    it('renders DateField for date type', () => {
      const field: ActionField = {
        type: 'date',
        label: 'Publish Date',
        description: 'The date to publish',
        required: false,
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="publish_date"
          field={field}
          value="2025-01-15"
        />,
      );
      expect(screen.getByTestId('date-field')).toBeInTheDocument();
      expect(screen.getByTestId('date-field')).toHaveAttribute('data-field-name', 'publish_date');
    });

    it('renders MultiSelectField for dynamic multi_select type', () => {
      const field: ActionField = {
        type: 'multi_select',
        label: 'Segments',
        description: 'Select segments',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/segments',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="segments"
          field={field}
          value={[]}
        />,
      );
      expect(screen.getByTestId('multi-select-field')).toBeInTheDocument();
      expect(screen.getByTestId('multi-select-field')).toHaveAttribute(
        'data-field-name',
        'segments',
      );
    });

    it('returns null for unsupported field types', () => {
      const field: ActionField = {
        type: 'unknown' as 'string',
        label: 'Unknown',
        description: '',
        required: false,
      };
      const { container } = render(
        <SchemaFieldRenderer {...defaultProps} fieldName="unknown" field={field} value="" />,
      );
      expect(container).toBeEmptyDOMElement();
    });
  });

  // ==========================================================================
  // Conditional Visibility Tests
  // ==========================================================================

  describe('conditional visibility', () => {
    it('renders field when visible_when condition is met', () => {
      const field: ActionField = {
        type: 'string',
        label: 'Slack Channel',
        description: '',
        required: false,
        visible_when: {
          field: 'notification_type',
          operator: 'equals',
          value: 'slack',
        },
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="slack_channel"
          field={field}
          value=""
          actionConfig={{ notification_type: 'slack' }}
        />,
      );
      expect(screen.getByTestId('string-field')).toBeInTheDocument();
    });

    it('hides field when visible_when condition is not met', () => {
      const field: ActionField = {
        type: 'string',
        label: 'Slack Channel',
        description: '',
        required: false,
        visible_when: {
          field: 'notification_type',
          operator: 'equals',
          value: 'slack',
        },
      };
      const { container } = render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="slack_channel"
          field={field}
          value=""
          actionConfig={{ notification_type: 'email' }}
        />,
      );
      expect(container).toBeEmptyDOMElement();
    });

    it('renders field when no visible_when condition is specified', () => {
      const field: ActionField = {
        type: 'string',
        label: 'Email',
        description: '',
        required: false,
      };
      render(<SchemaFieldRenderer {...defaultProps} fieldName="email" field={field} value="" />);
      expect(screen.getByTestId('string-field')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Combined Selector Tests
  // ==========================================================================

  describe('combined selector fields', () => {
    const mockAction: Action = {
      type: 'create_record',
      label: 'Create Record',
      integration: 'airtable',
      description: 'Creates a record in Airtable',
      output_fields: [],
      is_available: true,
      availability_reason: '',
      is_connected: true,
      requires_connection: false,
      schema: {
        table_id: {
          type: 'string',
          label: 'Table',
          description: '',
          required: false,
        },
        table_selector: {
          type: 'select',
          label: 'Select Table',
          description: '',
          required: false,
          selector_for: 'table_id',
          dynamic: true,
          endpoint: '/integrations/airtable/tables',
        },
      },
    };

    it('renders CombinedSelectorField for fields with selector_for', () => {
      const selectorField: ActionField = {
        type: 'select',
        label: 'Select Table',
        description: '',
        required: false,
        selector_for: 'table_id',
        dynamic: true,
        endpoint: '/integrations/airtable/tables',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="table_selector"
          field={selectorField}
          value=""
          currentAction={mockAction}
        />,
      );
      expect(screen.getByTestId('combined-selector-field')).toBeInTheDocument();
      expect(screen.getByTestId('combined-selector-field')).toHaveAttribute(
        'data-selector-name',
        'table_selector',
      );
      expect(screen.getByTestId('combined-selector-field')).toHaveAttribute(
        'data-target-name',
        'table_id',
      );
    });

    it('queues fetch for combined selector when dependency is met', () => {
      const selectorField: ActionField = {
        type: 'select',
        label: 'Select Table',
        description: '',
        required: false,
        selector_for: 'table_id',
        dynamic: true,
        endpoint: '/integrations/airtable/tables',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="table_selector"
          field={selectorField}
          value=""
          currentAction={mockAction}
        />,
      );
      expect(mockOnQueueFetch).toHaveBeenCalledWith(
        'table_selector',
        '/integrations/airtable/tables',
        undefined,
        {},
      );
    });

    it('passes options to combined selector from dynamicOptions', () => {
      const selectorField: ActionField = {
        type: 'select',
        label: 'Select Table',
        description: '',
        required: false,
        selector_for: 'table_id',
        dynamic: true,
        endpoint: '/integrations/airtable/tables',
        value_field: 'id',
        label_field: 'name',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="table_selector"
          field={selectorField}
          value=""
          currentAction={mockAction}
          dynamicOptions={{
            table_selector: [
              { id: 'tbl1', name: 'Table 1' },
              { id: 'tbl2', name: 'Table 2' },
            ],
          }}
        />,
      );
      expect(screen.getByTestId('combined-selector-field')).toHaveAttribute(
        'data-options-count',
        '2',
      );
    });
  });

  // ==========================================================================
  // Dynamic Select Tests
  // ==========================================================================

  describe('dynamic select fields', () => {
    it('queues fetch for dynamic select on mount', () => {
      const field: ActionField = {
        type: 'select',
        label: 'List',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/lists',
      };
      render(<SchemaFieldRenderer {...defaultProps} fieldName="list_id" field={field} value="" />);
      expect(mockOnQueueFetch).toHaveBeenCalledWith(
        'list_id',
        '/integrations/mailchimp/lists',
        undefined,
        {},
      );
    });

    it('does not queue fetch when already loading', () => {
      const field: ActionField = {
        type: 'select',
        label: 'List',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/lists',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="list_id"
          field={field}
          value=""
          loadingDynamicFields={{ list_id: true }}
        />,
      );
      expect(mockOnQueueFetch).not.toHaveBeenCalled();
    });

    it('does not queue fetch when options already exist', () => {
      const field: ActionField = {
        type: 'select',
        label: 'List',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/lists',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="list_id"
          field={field}
          value=""
          dynamicOptions={{
            list_id: [{ value: 'list1', label: 'List 1' }],
          }}
        />,
      );
      expect(mockOnQueueFetch).not.toHaveBeenCalled();
    });

    it('does not queue fetch when there is an error', () => {
      const field: ActionField = {
        type: 'select',
        label: 'List',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/lists',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="list_id"
          field={field}
          value=""
          dynamicFieldErrors={{ list_id: 'Failed to load' }}
        />,
      );
      expect(mockOnQueueFetch).not.toHaveBeenCalled();
    });

    it('passes loading state to DynamicSelectField', () => {
      const field: ActionField = {
        type: 'select',
        label: 'List',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/integrations/mailchimp/lists',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="list_id"
          field={field}
          value=""
          loadingDynamicFields={{ list_id: true }}
        />,
      );
      expect(screen.getByTestId('dynamic-select-field')).toHaveAttribute('data-loading', 'true');
    });
  });

  // ==========================================================================
  // Dependency Handling Tests
  // ==========================================================================

  describe('dependency handling', () => {
    const mockAction: Action = {
      type: 'add_tag',
      label: 'Add Tag',
      integration: 'mailchimp',
      description: 'Adds a tag to a contact',
      output_fields: [],
      is_available: true,
      availability_reason: '',
      is_connected: true,
      requires_connection: false,
      schema: {
        list_id: {
          type: 'select',
          label: 'List',
          description: '',
          required: false,
          dynamic: true,
          endpoint: '/lists',
        },
        tag_id: {
          type: 'select',
          label: 'Tag',
          description: '',
          required: false,
          dynamic: true,
          endpoint: '/tags',
          depends_on: 'list_id',
        },
      },
    };

    it('marks dependency as not met when depends_on value is empty', () => {
      const field: ActionField = {
        type: 'select',
        label: 'Tag',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/tags',
        depends_on: 'list_id',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="tag_id"
          field={field}
          value=""
          currentAction={mockAction}
          actionConfig={{ list_id: '' }}
        />,
      );
      expect(screen.getByTestId('dynamic-select-field')).toHaveAttribute(
        'data-dependency-met',
        'false',
      );
    });

    it('marks dependency as met when depends_on value is provided', () => {
      const field: ActionField = {
        type: 'select',
        label: 'Tag',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/tags',
        depends_on: 'list_id',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="tag_id"
          field={field}
          value=""
          currentAction={mockAction}
          actionConfig={{ list_id: 'list-123' }}
        />,
      );
      expect(screen.getByTestId('dynamic-select-field')).toHaveAttribute(
        'data-dependency-met',
        'true',
      );
    });

    it('queues fetch with dependency value', () => {
      const field: ActionField = {
        type: 'select',
        label: 'Tag',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/tags',
        depends_on: 'list_id',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="tag_id"
          field={field}
          value=""
          currentAction={mockAction}
          actionConfig={{ list_id: 'list-123' }}
        />,
      );
      expect(mockOnQueueFetch).toHaveBeenCalledWith('tag_id', '/tags', 'list-123', {
        list_id: 'list-123',
      });
    });

    it('uses cache key with dependency value', () => {
      const field: ActionField = {
        type: 'select',
        label: 'Tag',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/tags',
        depends_on: 'list_id',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="tag_id"
          field={field}
          value=""
          currentAction={mockAction}
          actionConfig={{ list_id: 'list-123' }}
          dynamicOptions={{
            'tag_id_list-123': [{ value: 'tag1', label: 'Tag 1' }],
          }}
        />,
      );
      expect(screen.getByTestId('dynamic-select-field')).toHaveAttribute('data-options-count', '1');
    });

    it('does not queue fetch when dependency not met', () => {
      const field: ActionField = {
        type: 'select',
        label: 'Tag',
        description: '',
        required: false,
        dynamic: true,
        endpoint: '/tags',
        depends_on: 'list_id',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="tag_id"
          field={field}
          value=""
          currentAction={mockAction}
          actionConfig={{ list_id: '' }}
        />,
      );
      expect(mockOnQueueFetch).not.toHaveBeenCalled();
    });
  });

  // ==========================================================================
  // Key Value Field Tests
  // ==========================================================================

  describe('key value fields', () => {
    it('renders KeyValueField with dependency met when no depends_on', () => {
      const field: ActionField = {
        type: 'key_value',
        label: 'Custom Fields',
        description: '',
        required: false,
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="custom_fields"
          field={field}
          value={{}}
        />,
      );
      expect(screen.getByTestId('key-value-field')).toHaveAttribute('data-dependency-met', 'true');
    });

    it('passes loading state to KeyValueField', () => {
      const field: ActionField = {
        type: 'key_value',
        label: 'Custom Fields',
        description: '',
        required: false,
        depends_on: 'table_id',
        dynamic_options: true,
        endpoint: '/fields',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="custom_fields"
          field={field}
          value={{}}
          actionConfig={{ table_id: 'tbl123' }}
          loadingDynamicFields={{ custom_fields_tbl123: true }}
        />,
      );
      expect(screen.getByTestId('key-value-field')).toHaveAttribute('data-loading', 'true');
    });

    it('queues fetch for key value field with dependency value', () => {
      const field: ActionField = {
        type: 'key_value',
        label: 'Custom Fields',
        description: '',
        required: false,
        depends_on: 'table_id',
        dynamic_options: true,
        endpoint: '/fields',
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="custom_fields"
          field={field}
          value={{}}
          actionConfig={{ table_id: 'tbl123' }}
        />,
      );
      expect(mockOnQueueFetch).toHaveBeenCalledWith('custom_fields', '/fields', 'tbl123', {
        table_id: 'tbl123',
      });
    });
  });

  // ==========================================================================
  // Filter Group Field Tests
  // ==========================================================================

  describe('filter group fields', () => {
    it('queues property fetch when property_source value changes', () => {
      const field: ActionField = {
        type: 'filter_group',
        label: 'Filters',
        description: '',
        required: false,
        filter_config: {
          operators: ['and', 'or'],
          condition_mappings: {},
          property_source: 'table_id',
          property_endpoint: '/properties',
        },
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="filters"
          field={field}
          value={undefined}
          actionConfig={{ table_id: 'tbl123' }}
        />,
      );
      expect(mockOnQueueFetch).toHaveBeenCalledWith('filters_properties', '/properties', 'tbl123', {
        table_id: 'tbl123',
      });
    });

    it('does not queue property fetch when properties already loaded', () => {
      const field: ActionField = {
        type: 'filter_group',
        label: 'Filters',
        description: '',
        required: false,
        filter_config: {
          operators: ['and', 'or'],
          condition_mappings: {},
          property_source: 'table_id',
          property_endpoint: '/properties',
        },
      };
      render(
        <SchemaFieldRenderer
          {...defaultProps}
          fieldName="filters"
          field={field}
          value={undefined}
          actionConfig={{ table_id: 'tbl123' }}
          dynamicOptions={{
            filters_properties_tbl123: [{ value: 'prop1', label: 'Property 1' }],
          }}
        />,
      );
      expect(mockOnQueueFetch).not.toHaveBeenCalled();
    });
  });
});
