import type { Inputs, ModelConfig } from '@/models/debug'
import type { PromptVariable } from '@/types/app'
import { fireEvent, render, screen } from '@testing-library/react'
import ChatUserInput from '../chat-user-input'

const mockSetInputs = vi.fn()
const mockUseContext = vi.fn()
vi.mock('use-context-selector', () => ({
  useContext: () => mockUseContext(),
  createContext: vi.fn(() => ({})),
}))

vi.mock('@/app/components/base/input', () => ({
  default: ({
    value,
    onChange,
    placeholder,
    autoFocus,
    maxLength,
    readOnly,
    type,
  }: {
    value: string
    onChange: (e: { target: { value: string } }) => void
    placeholder?: string
    autoFocus?: boolean
    maxLength?: number
    readOnly?: boolean
    type?: string
  }) => (
    <input
      data-testid={`input-${placeholder}`}
      data-autofocus={autoFocus ? 'true' : undefined}
      type={type || 'text'}
      value={value}
      onChange={onChange}
      placeholder={placeholder}
      maxLength={maxLength}
      readOnly={readOnly}
    />
  ),
}))

vi.mock('@langgenius/dify-ui/select', async () => {
  const React = await import('react')
  const SelectContext = React.createContext<{
    disabled?: boolean
    onValueChange?: (value: string) => void
  }>({})

  return {
    Select: ({
      children,
      disabled,
      onValueChange,
    }: {
      children: React.ReactNode
      disabled?: boolean
      onValueChange?: (value: string) => void
    }) => (
      <SelectContext.Provider value={{ disabled, onValueChange }}>
        <div>{children}</div>
      </SelectContext.Provider>
    ),
    SelectTrigger: ({ children, className }: { children: React.ReactNode; className?: string }) => {
      const context = React.useContext(SelectContext)
      return (
        <div>
          <button
            data-testid="select-input"
            type="button"
            disabled={context.disabled}
            className={className}
          >
            {children}
          </button>
          <button
            data-testid="select-empty"
            type="button"
            onClick={() => context.onValueChange?.('')}
          >
            empty select value
          </button>
        </div>
      )
    },
    SelectContent: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
    SelectItem: ({ children, value }: { children: React.ReactNode; value: string }) => {
      const context = React.useContext(SelectContext)
      return (
        <button
          data-testid={`select-${value}`}
          type="button"
          role="option"
          onClick={() => context.onValueChange?.(value)}
        >
          {children}
        </button>
      )
    },
    SelectItemText: ({ children }: { children: React.ReactNode }) => <>{children}</>,
    SelectItemIndicator: () => null,
  }
})

vi.mock('@/app/components/workflow/nodes/_base/components/before-run-form/bool-input', () => ({
  default: ({
    name,
    value,
    required,
    onChange,
    readonly,
  }: {
    name: string
    value: boolean
    required?: boolean
    onChange: (value: boolean) => void
    readonly?: boolean
  }) => (
    <div data-testid={`bool-input-${name}`}>
      <input
        type="checkbox"
        checked={value}
        onChange={(e) => onChange(e.target.checked)}
        disabled={readonly}
        data-required={required}
      />
      <span>{name}</span>
    </div>
  ),
}))

// Extended type to match runtime behavior (includes 'paragraph', 'checkbox', 'default')
type ExtendedPromptVariable = {
  key: string
  name: string
  type: 'string' | 'number' | 'select' | 'paragraph' | 'checkbox'
  required: boolean
  options?: string[]
  max_length?: number
  default?: string | null
}

const createPromptVariable = (
  overrides: Partial<ExtendedPromptVariable> = {},
): ExtendedPromptVariable => ({
  key: 'test-key',
  name: 'Test Name',
  type: 'string',
  required: false,
  ...overrides,
})

const createModelConfig = (promptVariables: ExtendedPromptVariable[] = []): ModelConfig =>
  ({
    provider: 'openai',
    model_id: 'gpt-4',
    mode: 'chat',
    configs: {
      prompt_template: '',
      prompt_variables: promptVariables as PromptVariable[],
    },
  }) as ModelConfig

const createContextValue = (
  overrides: Partial<{
    modelConfig: ModelConfig
    setInputs: (inputs: Inputs) => void
    readonly: boolean
    canTestAndRun: boolean
  }> = {},
) => ({
  modelConfig: createModelConfig(),
  setInputs: mockSetInputs,
  readonly: false,
  canTestAndRun: true,
  ...overrides,
})

describe('ChatUserInput', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockUseContext.mockReturnValue(createContextValue())
  })

  describe('Rendering', () => {
    it('should return null when no prompt variables exist', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([]),
        }),
      )

      const { container } = render(<ChatUserInput inputs={{}} />)
      expect(container.firstChild).toBeNull()
    })

    it('should return null when prompt variables have empty keys', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: '', name: 'Test' }),
            createPromptVariable({ key: '   ', name: 'Test2' }),
          ]),
        }),
      )

      const { container } = render(<ChatUserInput inputs={{}} />)
      expect(container.firstChild).toBeNull()
    })

    it('should return null when prompt variables have empty names', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'key1', name: '' }),
            createPromptVariable({ key: 'key2', name: '   ' }),
          ]),
        }),
      )

      const { container } = render(<ChatUserInput inputs={{}} />)
      expect(container.firstChild).toBeNull()
    })

    it('should render string input type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).toBeInTheDocument()
    })

    it('should render paragraph input type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'description', name: 'Description', type: 'paragraph' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByRole('textbox', { name: 'Description' })).toBeInTheDocument()
    })

    it('should render select input type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'choice',
              name: 'Choice',
              type: 'select',
              options: ['A', 'B', 'C'],
            }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('select-input')).toBeInTheDocument()
      expect(screen.getByText('A')).toBeInTheDocument()
      expect(screen.getByText('B')).toBeInTheDocument()
      expect(screen.getByText('C')).toBeInTheDocument()
    })

    it('should render number input type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'count', name: 'Count', type: 'number' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      const input = screen.getByTestId('input-Count')
      expect(input).toBeInTheDocument()
      expect(input).toHaveAttribute('type', 'number')
    })

    it('should render checkbox input type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'enabled', name: 'Enabled', type: 'checkbox' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('bool-input-Enabled')).toBeInTheDocument()
    })

    it('should render multiple input types', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
            createPromptVariable({ key: 'desc', name: 'Description', type: 'paragraph' }),
            createPromptVariable({
              key: 'choice',
              name: 'Choice',
              type: 'select',
              options: ['X', 'Y'],
            }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).toBeInTheDocument()
      expect(screen.getByRole('textbox', { name: 'Description' })).toBeInTheDocument()
      expect(screen.getByTestId('select-input')).toBeInTheDocument()
    })

    it('should show optional label for non-required fields', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string', required: false }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByText(/(?:^|\.)panel\.optional(?=$|:)/)).toBeInTheDocument()
    })

    it('should not show optional label for required fields', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string', required: true }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.queryByText(/(?:^|\.)panel\.optional(?=$|:)/)).not.toBeInTheDocument()
    })

    it('should use key as label when name is not provided', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'myKey', name: '', type: 'string' }),
          ]),
        }),
      )

      // This should actually return null because name is empty
      const { container } = render(<ChatUserInput inputs={{}} />)
      expect(container.firstChild).toBeNull()
    })
  })

  describe('Input Values', () => {
    it('should display existing input values for string type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ name: 'John' }} />)
      expect(screen.getByTestId('input-Name')).toHaveValue('John')
    })

    it('should display existing input values for paragraph type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'desc', name: 'Description', type: 'paragraph' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ desc: 'Long text here' }} />)
      expect(screen.getByRole('textbox', { name: 'Description' })).toHaveValue('Long text here')
    })

    it('should display existing input values for number type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'count', name: 'Count', type: 'number' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ count: 42 }} />)
      // Number type input still uses string value internally
      expect(screen.getByTestId('input-Count')).toHaveValue(42)
    })

    it('should display checkbox as checked when value is truthy', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'enabled', name: 'Enabled', type: 'checkbox' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ enabled: true }} />)
      const checkbox = screen.getByTestId('bool-input-Enabled').querySelector('input')
      expect(checkbox).toBeChecked()
    })

    it('should display checkbox as unchecked when value is falsy', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'enabled', name: 'Enabled', type: 'checkbox' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ enabled: false }} />)
      const checkbox = screen.getByTestId('bool-input-Enabled').querySelector('input')
      expect(checkbox).not.toBeChecked()
    })

    it('should handle empty string values', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ name: '' }} />)
      expect(screen.getByTestId('input-Name')).toHaveValue('')
    })

    it('should handle undefined values', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).toHaveValue('')
    })
  })

  describe('User Interactions', () => {
    it('should call setInputs when string input changes', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      fireEvent.change(screen.getByTestId('input-Name'), { target: { value: 'New Value' } })

      expect(mockSetInputs).toHaveBeenCalledWith({ name: 'New Value' })
    })

    it('should call setInputs when paragraph input changes', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'desc', name: 'Description', type: 'paragraph' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      fireEvent.change(screen.getByRole('textbox', { name: 'Description' }), {
        target: { value: 'New Description' },
      })

      expect(mockSetInputs).toHaveBeenCalledWith({ desc: 'New Description' })
    })

    it('should call setInputs when select input changes', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'choice',
              name: 'Choice',
              type: 'select',
              options: ['A', 'B', 'C'],
            }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ choice: 'A' }} />)
      fireEvent.click(screen.getByTestId('select-B'))

      expect(mockSetInputs).toHaveBeenCalledWith({ choice: 'B' })
    })

    it('should ignore empty select updates', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'choice',
              name: 'Choice',
              type: 'select',
              options: ['A', 'B', 'C'],
            }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      fireEvent.click(screen.getByTestId('select-empty'))

      expect(mockSetInputs).not.toHaveBeenCalled()
    })

    it('should call setInputs when number input changes', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'count', name: 'Count', type: 'number' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      fireEvent.change(screen.getByTestId('input-Count'), { target: { value: '100' } })

      expect(mockSetInputs).toHaveBeenCalledWith({ count: '100' })
    })

    it('should call setInputs when checkbox changes', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'enabled', name: 'Enabled', type: 'checkbox' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ enabled: false }} />)
      const checkbox = screen.getByTestId('bool-input-Enabled').querySelector('input')!
      fireEvent.click(checkbox)

      expect(mockSetInputs).toHaveBeenCalledWith({ enabled: true })
    })

    it('should not call setInputs for unknown keys', () => {
      const filteredPromptVariables = {
        length: 1,
        forEach: vi.fn(),
        map: (callback: (value: ExtendedPromptVariable, index: number) => unknown) => [
          callback(createPromptVariable({ key: 'name', name: 'Name', type: 'string' }), 0),
        ],
      }
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: {
            ...createModelConfig(),
            configs: {
              prompt_template: '',
              prompt_variables: {
                filter: () => filteredPromptVariables,
              } as unknown as PromptVariable[],
            },
          },
        }),
      )

      render(<ChatUserInput inputs={{}} />)

      fireEvent.change(screen.getByTestId('input-Name'), { target: { value: 'Valid' } })

      expect(mockSetInputs).not.toHaveBeenCalled()
    })
  })

  describe('Debug Permission', () => {
    it('should keep string input editable when configuration is readonly but test/run is allowed', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
          readonly: true,
          canTestAndRun: true,
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).not.toHaveAttribute('readonly')
    })

    it('should set string input as readonly when test/run is denied even if configuration is editable', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
          readonly: false,
          canTestAndRun: false,
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).toHaveAttribute('readonly')
    })

    it('should set string input as readonly when configuration is readonly and test/run is denied', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
          readonly: true,
          canTestAndRun: false,
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).toHaveAttribute('readonly')
    })

    it('should set paragraph input as readonly when configuration is readonly and test/run is denied', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'desc', name: 'Description', type: 'paragraph' }),
          ]),
          readonly: true,
          canTestAndRun: false,
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByRole('textbox', { name: 'Description' })).toHaveAttribute('readonly')
    })

    it('should disable select when configuration is readonly and test/run is denied', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'choice',
              name: 'Choice',
              type: 'select',
              options: ['A', 'B'],
            }),
          ]),
          readonly: true,
          canTestAndRun: false,
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('select-input')).toBeDisabled()
    })

    it('should disable checkbox when configuration is readonly and test/run is denied', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'enabled', name: 'Enabled', type: 'checkbox' }),
          ]),
          readonly: true,
          canTestAndRun: false,
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      const checkbox = screen.getByTestId('bool-input-Enabled').querySelector('input')
      expect(checkbox).toBeDisabled()
    })
  })

  describe('Default Values', () => {
    it('should initialize inputs with default values when field is empty', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'name',
              name: 'Name',
              type: 'string',
              default: 'Default Name',
            }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)

      expect(mockSetInputs).toHaveBeenCalledWith({ name: 'Default Name' })
    })

    it('should not override existing values with defaults', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string', default: 'Default' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ name: 'Existing Value' }} />)

      // setInputs should not be called since there's already a value
      expect(mockSetInputs).not.toHaveBeenCalled()
    })

    it('should handle multiple default values', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'name',
              name: 'Name',
              type: 'string',
              default: 'Default Name',
            }),
            createPromptVariable({ key: 'count', name: 'Count', type: 'number', default: '10' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)

      expect(mockSetInputs).toHaveBeenCalledWith({
        name: 'Default Name',
        count: '10',
      })
    })

    it('should not set default when default is empty string', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string', default: '' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)

      expect(mockSetInputs).not.toHaveBeenCalled()
    })

    it('should not set default when default is undefined', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)

      expect(mockSetInputs).not.toHaveBeenCalled()
    })

    it('should not set default when default is null', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({
              key: 'name',
              name: 'Name',
              type: 'string',
              default: null as unknown as string,
            }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)

      expect(mockSetInputs).not.toHaveBeenCalled()
    })
  })

  describe('AutoFocus', () => {
    it('should set autoFocus on first string input', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'first', name: 'First', type: 'string' }),
            createPromptVariable({ key: 'second', name: 'Second', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-First')).toHaveAttribute('data-autofocus', 'true')
      expect(screen.getByTestId('input-Second')).not.toHaveAttribute('data-autofocus')
    })

    it('should set autoFocus on first number input when it is the first field', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'count', name: 'Count', type: 'number' }),
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Count')).toHaveAttribute('data-autofocus', 'true')
    })
  })

  describe('MaxLength', () => {
    it('should pass maxLength to string input', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string', max_length: 50 }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Name')).toHaveAttribute('maxLength', '50')
    })

    it('should pass maxLength to number input', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'count', name: 'Count', type: 'number', max_length: 10 }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      expect(screen.getByTestId('input-Count')).toHaveAttribute('maxLength', '10')
    })
  })

  describe('Edge Cases', () => {
    it('should handle select with empty options', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'choice', name: 'Choice', type: 'select', options: [] }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      const select = screen.getByTestId('select-input')
      expect(select).toBeInTheDocument()
      expect(screen.queryAllByRole('option')).toHaveLength(0)
    })

    it('should handle select with undefined options', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'choice', name: 'Choice', type: 'select' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      const select = screen.getByTestId('select-input')
      expect(select).toBeInTheDocument()
    })

    it('should preserve other input values when updating one field', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'name', name: 'Name', type: 'string' }),
            createPromptVariable({ key: 'desc', name: 'Description', type: 'paragraph' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ name: 'Existing', desc: 'Also Existing' }} />)
      fireEvent.change(screen.getByTestId('input-Name'), { target: { value: 'Updated' } })

      expect(mockSetInputs).toHaveBeenCalledWith({
        name: 'Updated',
        desc: 'Also Existing',
      })
    })

    it('should convert non-string values to string for display', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'value', name: 'Value', type: 'string' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{ value: 123 as unknown as string }} />)
      expect(screen.getByTestId('input-Value')).toHaveValue('123')
    })

    it('should not hide label for checkbox type', () => {
      mockUseContext.mockReturnValue(
        createContextValue({
          modelConfig: createModelConfig([
            createPromptVariable({ key: 'enabled', name: 'Is Enabled', type: 'checkbox' }),
          ]),
        }),
      )

      render(<ChatUserInput inputs={{}} />)
      // For checkbox, the label is rendered inside BoolInput, not in the header
      expect(screen.queryByText('Is Enabled')).toBeInTheDocument()
    })
  })
})
