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

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

  test('renders empty container when widget does not exist', () => {
    const { container } = render(<FormulaUI id='non-existent' />)
    // Box wrapper is rendered but Row returns null for missing widget
    expect(container.firstChild?.childNodes.length).toBe(0)
  })

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

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('$')).toBeTruthy()
    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('USD')).toBeTruthy()
  })

  test('renders with multiple data items', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, prefix: '$' },
        { value: 200, suffix: '%' },
        { value: 300 },
      ],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('$')).toBeTruthy()
    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('200')).toBeTruthy()
    expect(screen.getByText('%')).toBeTruthy()
    expect(screen.getByText('300')).toBeTruthy()
  })

  test('renders Prefix component for each item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, prefix: 'Item 1:' },
        { value: 200, prefix: 'Item 2:' },
      ],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('Item 1:')).toBeTruthy()
    expect(screen.getByText('Item 2:')).toBeTruthy()
  })

  test('renders Value component for each item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 100 }, { value: 200 }],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('200')).toBeTruthy()
  })

  test('renders Suffix component for each item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, suffix: 'units' },
        { value: 200, suffix: 'items' },
      ],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('units')).toBeTruthy()
    expect(screen.getByText('items')).toBeTruthy()
  })

  test('renders in correct order: Prefix, Value, Suffix', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 100, prefix: '$', suffix: 'USD' }],
    })

    const { container } = render(<FormulaUI id='test-formula' />)

    const items = container.querySelectorAll('.MuiTypography-root')
    expect(items.length).toBe(3)
    expect(items[0]?.textContent).toBe('$')
    expect(items[1]?.textContent).toBe('100')
    expect(items[2]?.textContent).toBe('USD')
  })

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

    render(<FormulaUI id='test-formula' />)

    expect(screen.queryByText('$')).toBeNull()
    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('USD')).toBeTruthy()
  })

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

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('$')).toBeTruthy()
    expect(screen.getByText('100')).toBeTruthy()
    // Suffix should not be rendered
    const items = screen.queryAllByText('USD')
    expect(items.length).toBe(0)
  })

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

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('100')).toBeTruthy()
  })

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

    const { container } = render(<FormulaUI id='test-formula' />)

    // Row component returns null for empty data, Box wrapper still rendered
    expect(container.firstChild?.childNodes.length).toBe(0)
  })

  test('handles undefined data', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
    })

    const { container } = render(<FormulaUI id='test-formula' />)

    // Row component returns null for undefined data, Box wrapper still rendered
    expect(container.firstChild?.childNodes.length).toBe(0)
  })

  test('passes correct index to child components', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, prefix: 'First' },
        { value: 200, prefix: 'Second' },
        { value: 300, prefix: 'Third' },
      ],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('First')).toBeTruthy()
    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('Second')).toBeTruthy()
    expect(screen.getByText('200')).toBeTruthy()
    expect(screen.getByText('Third')).toBeTruthy()
    expect(screen.getByText('300')).toBeTruthy()
  })

  test('renders with data containing colors', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, color: '#FF0000' },
        { value: 200, color: '#00FF00' },
      ],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('200')).toBeTruthy()
  })

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

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('-')).toBeTruthy()
    expect(screen.getByText('-100')).toBeTruthy()
  })

  test('renders with zero value', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 0 }],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('0')).toBeTruthy()
  })

  test('renders with decimal values', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 123.456, suffix: 'km' }],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('123.456')).toBeTruthy()
    expect(screen.getByText('km')).toBeTruthy()
  })

  test('renders with large values', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 1000000000, prefix: '$' }],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('$')).toBeTruthy()
    expect(screen.getByText('1000000000')).toBeTruthy()
  })

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

    const { rerender } = render(<FormulaUI id='test-formula' />)
    expect(screen.getByText('100')).toBeTruthy()

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

    rerender(<FormulaUI id='test-formula' />)
    expect(screen.queryByText('100')).toBeNull()
    expect(screen.getByText('200')).toBeTruthy()
  })

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

    const { container, rerender } = render(<FormulaUI id='test-formula' />)
    expect(screen.getByText('100')).toBeTruthy()

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

    rerender(<FormulaUI id='test-formula' />)
    // Box wrapper still rendered but Row returns null
    expect(container.firstChild?.childNodes.length).toBe(0)
  })

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

    const { container } = render(<FormulaUI id='test-formula' />)

    // Empty prefix should not render
    expect(container.firstChild).toBeTruthy()
    expect(screen.getByText('100')).toBeTruthy()
  })

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

    const { container } = render(<FormulaUI id='test-formula' />)

    // Empty suffix should not render
    expect(container.firstChild).toBeTruthy()
    expect(screen.getByText('100')).toBeTruthy()
  })

  test('renders multiple rows for multiple data items', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, prefix: 'A' },
        { value: 200, prefix: 'B' },
        { value: 300, prefix: 'C' },
      ],
    })

    const { container } = render(<FormulaUI id='test-formula' />)

    // Each data item should create a row
    const rows = container.querySelectorAll('[class*="MuiBox-root"]')
    expect(rows.length).toBeGreaterThan(0)
  })

  test('renders with single series in array', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 100, suffix: 'units' }],
      series: [{ name: 'Category A' }],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('C')).toBeTruthy() // Avatar shows first letter
    expect(screen.getByText('100')).toBeTruthy()
  })

  test('renders with series and custom color', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [{ value: 100 }],
      series: [{ name: 'Sales', color: '#FF0000' }],
    })

    const { container } = render(<FormulaUI id='test-formula' />)

    const avatar = container.querySelector('.MuiAvatar-root')
    expect(avatar).toBeTruthy()
    expect(screen.getByText('S')).toBeTruthy() // First letter of 'Sales'
  })

  test('renders with array of series matching data indices', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, suffix: 'units' },
        { value: 200, suffix: 'items' },
        { value: 300, suffix: 'pieces' },
      ],
      series: [
        { name: 'Alpha', color: '#FF0000' },
        { name: 'Beta', color: '#00FF00' },
        { name: 'Gamma', color: '#0000FF' },
      ],
    })

    render(<FormulaUI id='test-formula' />)

    expect(screen.getByText('A')).toBeTruthy() // Alpha
    expect(screen.getByText('B')).toBeTruthy() // Beta
    expect(screen.getByText('G')).toBeTruthy() // Gamma
    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('200')).toBeTruthy()
    expect(screen.getByText('300')).toBeTruthy()
  })

  test('renders partial series array - only shows series for available indices', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-formula', {
      type: 'formula',
      data: [
        { value: 100, suffix: 'units' },
        { value: 200, suffix: 'items' },
        { value: 300, suffix: 'pieces' },
      ],
      series: [{ name: 'Only First', color: '#FF0000' }],
    })

    render(<FormulaUI id='test-formula' />)

    // Only first row should have series avatar
    expect(screen.getByText('O')).toBeTruthy() // Only First
    expect(screen.getByText('100')).toBeTruthy()
    expect(screen.getByText('200')).toBeTruthy()
    expect(screen.getByText('300')).toBeTruthy()
  })
})
