import { withSelectorKey } from '@/test/i18n-mock'
import { ChatVarType } from '../../type'
import {
  buildObjectValueItems,
  formatChatVariableValue,
  formatObjectValueFromList,
  getEditorMinHeight,
  getEditorToggleLabelKey,
  getPlaceholderByType,
  getTypeChangeState,
  parseEditorContent,
  validateVariableName,
} from '../variable-modal.helpers'

describe('variable-modal helpers', () => {
  it('should build object items from a conversation variable value', () => {
    expect(buildObjectValueItems()).toHaveLength(1)

    expect(
      buildObjectValueItems({
        id: 'var-1',
        name: 'config',
        description: '',
        value_type: ChatVarType.Object,
        value: { apiKey: 'secret', timeout: 30 },
      }),
    ).toEqual([
      { key: 'apiKey', type: ChatVarType.String, value: 'secret' },
      { key: 'timeout', type: ChatVarType.Number, value: 30 },
    ])
  })

  it('should format object and array values for saving', () => {
    expect(
      formatObjectValueFromList([
        { key: 'apiKey', type: ChatVarType.String, value: 'secret' },
        { key: '', type: ChatVarType.Number, value: 1 },
      ]),
    ).toEqual({ apiKey: 'secret' })

    expect(
      formatObjectValueFromList([
        { key: 'count', type: ChatVarType.Number, value: 0 },
        { key: 'label', type: ChatVarType.String, value: '' },
      ]),
    ).toEqual({ count: 0, label: null })
    expect(
      formatChatVariableValue({
        editInJSON: false,
        objectValue: [{ key: 'enabled', type: ChatVarType.String, value: 'true' }],
        type: ChatVarType.Object,
        value: undefined,
      }),
    ).toEqual({ enabled: 'true' })

    expect(
      formatChatVariableValue({
        editInJSON: true,
        objectValue: [],
        type: ChatVarType.Object,
        value: { count: 1 },
      }),
    ).toEqual({ count: 1 })

    expect(
      formatChatVariableValue({
        editInJSON: false,
        objectValue: [],
        type: ChatVarType.ArrayString,
        value: ['a', '', 'b'],
      }),
    ).toEqual(['a', 'b'])

    expect(
      formatChatVariableValue({
        editInJSON: false,
        objectValue: [],
        type: ChatVarType.ArrayNumber,
        value: [0, 1, undefined, null, ''] as unknown as Array<number | undefined>,
      }),
    ).toEqual([0, 1])

    expect(
      formatChatVariableValue({
        editInJSON: false,
        objectValue: [],
        type: ChatVarType.Number,
        value: undefined,
      }),
    ).toBe(0)

    expect(
      formatChatVariableValue({
        editInJSON: false,
        objectValue: [],
        type: ChatVarType.Boolean,
        value: undefined,
      }),
    ).toBe(true)

    expect(
      formatChatVariableValue({
        editInJSON: false,
        objectValue: [],
        type: ChatVarType.ArrayBoolean,
        value: undefined,
      }),
    ).toEqual([])
  })

  it('should derive placeholders, editor defaults, and editor toggle labels', () => {
    expect(getEditorMinHeight(ChatVarType.ArrayObject)).toBe('240px')
    expect(getEditorMinHeight(ChatVarType.Object)).toBe('120px')
    expect(getPlaceholderByType(ChatVarType.ArrayBoolean)).toBeTruthy()
    expect(getTypeChangeState(ChatVarType.Boolean).value).toBe(false)
    expect(getTypeChangeState(ChatVarType.ArrayBoolean).value).toEqual([false])
    expect(getTypeChangeState(ChatVarType.Object).objectValue).toHaveLength(1)
    expect(getTypeChangeState(ChatVarType.ArrayObject).editInJSON).toBe(true)
    expect(getEditorToggleLabelKey(ChatVarType.Object, true)).toBe('chatVariable.modal.editInForm')
    expect(getEditorToggleLabelKey(ChatVarType.ArrayString, false)).toBe(
      'chatVariable.modal.editInJSON',
    )
  })

  it('should parse boolean arrays from JSON editor content', () => {
    expect(
      parseEditorContent({
        content: '["True","false",true,false,"invalid"]',
        type: ChatVarType.ArrayBoolean,
      }),
    ).toEqual([true, false, true, false])

    expect(() =>
      parseEditorContent({
        content: '{"enabled":true}',
        type: ChatVarType.ArrayBoolean,
      }),
    ).toThrow('JSON array')
    expect(
      parseEditorContent({
        content: '{"enabled":true}',
        type: ChatVarType.Object,
      }),
    ).toEqual({ enabled: true })
  })

  it('should validate variable names and notify when invalid', () => {
    const notify = vi.fn()
    const t = withSelectorKey((key: string) => key)

    expect(
      validateVariableName({
        name: 'valid_name',
        notify,
        t,
      }),
    ).toBe(true)

    expect(
      validateVariableName({
        name: '1invalid',
        notify,
        t,
      }),
    ).toBe(false)

    expect(notify).toHaveBeenCalledWith(
      expect.objectContaining({
        type: 'error',
      }),
    )
  })
})
