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

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

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('USD')).toBeTruthy()
  })

  test('renders suffix at specified index', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-suffix', {
      type: 'formula',
      data: [
        { value: 100, suffix: 'units' },
        { value: 200, suffix: 'items' },
        { value: 300, suffix: 'pieces' },
      ],
    })

    render(<Suffix id='test-suffix' index={1} />)
    expect(screen.getByText('items')).toBeTruthy()
  })

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('first')).toBeTruthy()
  })

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

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

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

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

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

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

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

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

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

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

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

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('meters')).toBeTruthy()
  })

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('%')).toBeTruthy()
  })

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('square meters')).toBeTruthy()
  })

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

    render(<Suffix id='test-suffix' />)
    const element = screen.getByText('%')
    expect(element.tagName).toBe('H5')
  })

  test('applies secondary text color', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-suffix', {
      type: 'formula',
      data: [{ value: 100, suffix: 'USD' }],
    })

    render(<Suffix id='test-suffix' />)
    const element = screen.getByText('USD')
    // TypographyProps receives a function for color, so we check the element exists
    expect(element).toBeTruthy()
  })

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

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

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

    render(
      <Suffix id='test-suffix' 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-suffix', {
      type: 'formula',
      data: [
        {
          value: 100,
          color: '#FF0000',
          prefix: '$',
          suffix: 'USD',
        },
      ],
    })

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('USD')).toBeTruthy()
  })

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

    const { rerender } = render(<Suffix id='test-suffix' />)
    expect(screen.getByText('USD')).toBeTruthy()

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

    rerender(<Suffix id='test-suffix' />)
    expect(screen.queryByText('USD')).toBeNull()
    expect(screen.getByText('EUR')).toBeTruthy()
  })

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

    const { container, rerender } = render(<Suffix id='test-suffix' />)
    expect(screen.getByText('USD')).toBeTruthy()

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

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

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

    const { rerender } = render(<Suffix id='test-suffix' index={0} />)
    expect(screen.getByText('USD')).toBeTruthy()

    rerender(<Suffix id='test-suffix' index={1} />)
    expect(screen.queryByText('USD')).toBeNull()
    expect(screen.getByText('EUR')).toBeTruthy()
  })

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

    const { container, rerender } = render(<Suffix id='test-suffix' />)
    expect(screen.getByText('USD')).toBeTruthy()

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

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

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('m²')).toBeTruthy()
  })

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText(/€ coins/)).toBeTruthy()
  })

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

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText('x10')).toBeTruthy()
  })

  test('handles long suffix text', () => {
    const longSuffix = ' units per square meter per second'
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-suffix', {
      type: 'formula',
      data: [{ value: 100, suffix: longSuffix }],
    })

    render(<Suffix id='test-suffix' />)
    expect(screen.getByText(longSuffix.trim())).toBeTruthy()
  })

  test('renders different suffixes for different items', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-suffix', {
      type: 'formula',
      data: [
        { value: 100, suffix: 'USD' },
        { value: 200, suffix: 'EUR' },
        { value: 300, suffix: 'GBP' },
      ],
    })

    const { unmount } = render(<Suffix id='test-suffix' index={0} />)
    expect(screen.getByText('USD')).toBeTruthy()
    unmount()

    render(<Suffix id='test-suffix' index={1} />)
    expect(screen.getByText('EUR')).toBeTruthy()
  })

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

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

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

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

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

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

  test('secondary color is applied via TypographyProps', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-suffix', {
      type: 'formula',
      data: [{ value: 100, suffix: 'units' }],
    })

    render(<Suffix id='test-suffix' />)
    const element = screen.getByText('units')
    // The component passes a function for color, so we just verify it renders
    expect(element).toBeTruthy()
  })

  test('combines disabled and TypographyProps', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-suffix', {
      type: 'formula',
      data: [{ value: 100, suffix: 'units' }],
    })

    render(
      <Suffix
        id='test-suffix'
        disabled={true}
        TypographyProps={{ className: 'custom' }}
      />,
    )
    const element = screen.getByText('units')
    expect(element.getAttribute('data-disabled')).toBe('true')
    expect(element.classList.contains('custom')).toBe(true)
  })
})
