import { describe, test, expect, beforeEach } from 'vitest'
import { render, screen } from '@testing-library/react'
import { Prefix } from './prefix'
import { useWidgetStore } from '../../stores/widget-store'
import type { FormulaWidgetState } from '../types'

describe('Prefix', () => {
  beforeEach(() => {
    useWidgetStore.getState().clearWidgets()
  })

  test('renders prefix from widget data at default index 0', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('$')).toBeTruthy()
  })

  test('renders prefix at specified index', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [
        { value: 100, prefix: 'First' },
        { value: 200, prefix: 'Second' },
        { value: 300, prefix: 'Third' },
      ],
    })

    render(<Prefix id='test-prefix' index={1} />)
    expect(screen.getByText('Second')).toBeTruthy()
  })

  test('renders prefix at index 0 when index not specified', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [
        { value: 100, prefix: 'First' },
        { value: 200, prefix: 'Second' },
      ],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('First')).toBeTruthy()
  })

  test('returns null when widget does not exist', () => {
    const { container } = render(<Prefix id='non-existent' />)
    expect(container.firstChild).toBeNull()
  })

  test('returns null when widget data is undefined', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
    })

    const { container } = render(<Prefix id='test-prefix' />)
    expect(container.firstChild).toBeNull()
  })

  test('returns null when prefix is undefined', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    const { container } = render(<Prefix id='test-prefix' />)
    expect(container.firstChild).toBeNull()
  })

  test('returns null when index is out of bounds', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    const { container } = render(<Prefix id='test-prefix' index={5} />)
    expect(container.firstChild).toBeNull()
  })

  test('returns null for empty data array', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [],
    })

    const { container } = render(<Prefix id='test-prefix' />)
    expect(container.firstChild).toBeNull()
  })

  test('returns null for empty string prefix', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '' }],
    })

    const { container } = render(<Prefix id='test-prefix' />)
    expect(container.firstChild).toBeNull()
  })

  test('renders string prefix', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: 'Total:' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('Total:')).toBeTruthy()
  })

  test('renders single character prefix', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('$')).toBeTruthy()
  })

  test('renders multi-word prefix', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: 'Grand Total:' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('Grand Total:')).toBeTruthy()
  })

  test('renders as Typography h5', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    render(<Prefix id='test-prefix' />)
    const element = screen.getByText('$')
    expect(element.tagName).toBe('H5')
  })

  test('passes disabled prop to Item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    render(<Prefix id='test-prefix' disabled={true} />)
    const element = screen.getByText('$')
    expect(element.getAttribute('data-disabled')).toBe('true')
  })

  test('passes TypographyProps to Item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    render(
      <Prefix id='test-prefix' TypographyProps={{ className: 'custom' }} />,
    )
    const element = screen.getByText('$')
    expect(element.classList.contains('custom')).toBe(true)
  })

  test('handles all data properties together', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [
        {
          value: 100,
          color: '#FF0000',
          prefix: '$',
          suffix: 'USD',
        },
      ],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('$')).toBeTruthy()
  })

  test('updates when widget data changes', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    const { rerender } = render(<Prefix id='test-prefix' />)
    expect(screen.getByText('$')).toBeTruthy()

    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      data: [{ value: 200, prefix: '€' }],
    })

    rerender(<Prefix id='test-prefix' />)
    expect(screen.queryByText('$')).toBeNull()
    expect(screen.getByText('€')).toBeTruthy()
  })

  test('updates when prefix is removed', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    const { container, rerender } = render(<Prefix id='test-prefix' />)
    expect(screen.getByText('$')).toBeTruthy()

    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      data: [{ value: 100 }],
    })

    rerender(<Prefix id='test-prefix' />)
    expect(container.firstChild).toBeNull()
  })

  test('updates when index changes', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [
        { value: 100, prefix: '$' },
        { value: 200, prefix: '€' },
      ],
    })

    const { rerender } = render(<Prefix id='test-prefix' index={0} />)
    expect(screen.getByText('$')).toBeTruthy()

    rerender(<Prefix id='test-prefix' index={1} />)
    expect(screen.queryByText('$')).toBeNull()
    expect(screen.getByText('€')).toBeTruthy()
  })

  test('handles widget removal gracefully', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    const { container, rerender } = render(<Prefix id='test-prefix' />)
    expect(screen.getByText('$')).toBeTruthy()

    useWidgetStore.getState().removeWidget('test-prefix')

    rerender(<Prefix id='test-prefix' />)
    expect(container.firstChild).toBeNull()
  })

  test('handles prefix with special characters', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '¥' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('¥')).toBeTruthy()
  })

  test('handles prefix with unicode characters', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '€ 💰' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText(/€ 💰/)).toBeTruthy()
  })

  test('handles prefix with numbers', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '#1:' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('#1:')).toBeTruthy()
  })

  test('handles long prefix text', () => {
    const longPrefix = 'This is a very long prefix text: '
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: longPrefix }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText(longPrefix.trim())).toBeTruthy()
  })

  test('renders different prefixes for different items', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [
        { value: 100, prefix: '$' },
        { value: 200, prefix: '€' },
        { value: 300, prefix: '£' },
      ],
    })

    const { unmount } = render(<Prefix id='test-prefix' index={0} />)
    expect(screen.getByText('$')).toBeTruthy()
    unmount()

    render(<Prefix id='test-prefix' index={1} />)
    expect(screen.getByText('€')).toBeTruthy()
  })

  test('handles negative index (invalid but should not crash)', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '$' }],
    })

    const { container } = render(<Prefix id='test-prefix' index={-1} />)
    expect(container.firstChild).toBeNull()
  })

  test('handles prefix with only whitespace', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: '   ' }],
    })

    const { container } = render(<Prefix id='test-prefix' />)
    // Whitespace is normalized by text content, just verify component renders
    expect(container.querySelector('.MuiTypography-root')).toBeTruthy()
  })

  test('prefix is sanitized to string only in store', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-prefix', {
      type: 'formula',
      data: [{ value: 100, prefix: 'Valid String' }],
    })

    render(<Prefix id='test-prefix' />)
    expect(screen.getByText('Valid String')).toBeTruthy()
  })
})
