/**
 * Tests for CategoryRowSingle and CategoryRowMulti — both files share the
 * same conditional-render branches (onClick presence, labelFormatter
 * presence, selected default).
 */
import { describe, it, expect, vi } from 'vitest'
import { render, fireEvent } from '@testing-library/react'
import { ThemeProvider, createTheme } from '@mui/material/styles'
import { CategoryRowSingle } from './category-row-single'
import { CategoryRowMulti } from './category-row-multi'

const theme = createTheme({})
function renderWithTheme(ui: React.ReactElement) {
  return render(<ThemeProvider theme={theme}>{ui}</ThemeProvider>)
}

const formatter = (v: number) => `${v}`

describe('CategoryRowSingle', () => {
  it('renders the name and formatted value', () => {
    const { getByText } = renderWithTheme(
      <CategoryRowSingle
        name='Category A'
        value={42}
        maxValue={100}
        color='#f00'
        formatter={formatter}
      />,
    )
    expect(getByText('Category A')).toBeDefined()
    expect(getByText('42')).toBeDefined()
  })

  it('applies labelFormatter when provided', () => {
    const { getByText } = renderWithTheme(
      <CategoryRowSingle
        name='raw'
        value={10}
        maxValue={100}
        color='#f00'
        formatter={formatter}
        labelFormatter={(s) => `[${s}]`}
      />,
    )
    expect(getByText('[raw]')).toBeDefined()
  })

  it('invokes onClick with the row name when clicked', () => {
    const onClick = vi.fn()
    const { getByText } = renderWithTheme(
      <CategoryRowSingle
        name='X'
        value={1}
        maxValue={10}
        color='#f00'
        formatter={formatter}
        onClick={onClick}
      />,
    )
    fireEvent.click(getByText('X'))
    expect(onClick).toHaveBeenCalledWith({ name: 'X' })
  })

  it('renders without onClick (handleClick=undefined branch)', () => {
    expect(() =>
      renderWithTheme(
        <CategoryRowSingle
          name='Y'
          value={1}
          maxValue={10}
          color='#f00'
          formatter={formatter}
        />,
      ),
    ).not.toThrow()
  })

  it('respects selected=false', () => {
    expect(() =>
      renderWithTheme(
        <CategoryRowSingle
          name='Z'
          value={1}
          maxValue={10}
          color='#f00'
          formatter={formatter}
          selected={false}
        />,
      ),
    ).not.toThrow()
  })
})

describe('CategoryRowMulti', () => {
  it('renders the name and one bar per value', () => {
    const { getByText, getAllByText } = renderWithTheme(
      <CategoryRowMulti
        name='Multi A'
        values={[1, 2, 3]}
        maxValue={10}
        colors={['#f00', '#0f0', '#00f']}
        formatter={formatter}
      />,
    )
    expect(getByText('Multi A')).toBeDefined()
    expect(getAllByText('1')).toHaveLength(1)
    expect(getAllByText('2')).toHaveLength(1)
    expect(getAllByText('3')).toHaveLength(1)
  })

  it('applies labelFormatter when provided', () => {
    const { getByText } = renderWithTheme(
      <CategoryRowMulti
        name='raw'
        values={[1]}
        maxValue={10}
        colors={['#f00']}
        formatter={formatter}
        labelFormatter={(s) => `<${s}>`}
      />,
    )
    expect(getByText('<raw>')).toBeDefined()
  })

  it('invokes onClick with the row name when clicked', () => {
    const onClick = vi.fn()
    const { getByText } = renderWithTheme(
      <CategoryRowMulti
        name='ClickRow'
        values={[1, 2]}
        maxValue={10}
        colors={['#f00', '#0f0']}
        formatter={formatter}
        onClick={onClick}
      />,
    )
    fireEvent.click(getByText('ClickRow'))
    expect(onClick).toHaveBeenCalledWith({ name: 'ClickRow' })
  })

  it('renders without onClick', () => {
    expect(() =>
      renderWithTheme(
        <CategoryRowMulti
          name='N'
          values={[1, 2]}
          maxValue={10}
          colors={['#f00', '#0f0']}
          formatter={formatter}
        />,
      ),
    ).not.toThrow()
  })

  it('cycles colors when values.length exceeds colors.length (modulo branch)', () => {
    // 4 values, 2 colors → uses modulo to cycle (colors[index % colors.length])
    expect(() =>
      renderWithTheme(
        <CategoryRowMulti
          name='Cycle'
          values={[1, 2, 3, 4]}
          maxValue={10}
          colors={['#f00', '#0f0']}
          formatter={formatter}
        />,
      ),
    ).not.toThrow()
  })

  it('handles colors[i % colors.length] being undefined (?? "" fallback)', () => {
    // Empty colors array → colors[0 % 0] === undefined → falls back to ''
    expect(() =>
      renderWithTheme(
        <CategoryRowMulti
          name='Empty'
          values={[1, 2]}
          maxValue={10}
          colors={[]}
          formatter={formatter}
        />,
      ),
    ).not.toThrow()
  })

  it('respects selected=false', () => {
    expect(() =>
      renderWithTheme(
        <CategoryRowMulti
          name='Sel'
          values={[1]}
          maxValue={10}
          colors={['#f00']}
          formatter={formatter}
          selected={false}
        />,
      ),
    ).not.toThrow()
  })

  it('renders an empty bar container when values is empty', () => {
    expect(() =>
      renderWithTheme(
        <CategoryRowMulti
          name='Z'
          values={[]}
          maxValue={10}
          colors={['#f00']}
          formatter={formatter}
        />,
      ),
    ).not.toThrow()
  })
})
