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

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

  test('returns null when widget does not exist', () => {
    const { container } = render(
      <Row id='non-existent'>
        <div>Content</div>
      </Row>,
    )

    expect(container.firstChild).toBeNull()
  })

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

    const { container } = render(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    expect(container.firstChild).toBeNull()
  })

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

    const { container } = render(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    // map returns empty array, which renders nothing
    expect(container.firstChild).toBeNull()
  })

  test('renders direct children for single data item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    const { container } = render(
      <Row id='test-row'>
        <div data-testid='child'>Content</div>
      </Row>,
    )

    expect(container.querySelector('[data-testid="child"]')).toBeTruthy()
  })

  test('renders direct children for multiple data items', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }, { value: 200 }, { value: 300 }],
    })

    const { container } = render(
      <Row id='test-row'>
        <div className='child'>Content</div>
      </Row>,
    )

    const children = container.querySelectorAll('.child')
    expect(children.length).toBe(3)
  })

  test('calls render prop function with correct index for single item', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    const { container } = render(
      <Row id='test-row'>
        {({ index }) => <div data-index={index}>Index: {index}</div>}
      </Row>,
    )

    const element = container.querySelector('[data-index="0"]')
    expect(element).toBeTruthy()
    expect(element?.textContent).toBe('Index: 0')
  })

  test('calls render prop function with correct indices for multiple items', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }, { value: 200 }, { value: 300 }],
    })

    const { container } = render(
      <Row id='test-row'>
        {({ index }) => <div data-index={index}>Index: {index}</div>}
      </Row>,
    )

    expect(container.querySelector('[data-index="0"]')).toBeTruthy()
    expect(container.querySelector('[data-index="1"]')).toBeTruthy()
    expect(container.querySelector('[data-index="2"]')).toBeTruthy()
  })

  test('applies row flexbox styles to each row', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    const { container } = render(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    // Check that Box elements are rendered (we can't directly test sx styles)
    expect(container.firstChild).toBeTruthy()
  })

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

    const { container } = render(
      <Row id='test-row'>{({ index }) => <span>Row {index}</span>}</Row>,
    )

    const boxes = container.querySelectorAll('.MuiBox-root')
    expect(boxes.length).toBe(2)
  })

  test('assigns correct key to each row', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }, { value: 200 }, { value: 300 }],
    })

    const { container } = render(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    // Each data item should create a row
    const boxes = container.querySelectorAll('.MuiBox-root')
    expect(boxes.length).toBe(3)
  })

  test('handles render prop returning null', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    const { container } = render(<Row id='test-row'>{() => null}</Row>)

    // Row should still render Box, but with null children
    expect(container.firstChild).toBeTruthy()
  })

  test('handles render prop returning multiple elements', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    const { container } = render(
      <Row id='test-row'>
        {({ index }) => (
          <>
            <span>A</span>
            <span>B</span>
            <span>{index}</span>
          </>
        )}
      </Row>,
    )

    const spans = container.querySelectorAll('span')
    expect(spans.length).toBe(3)
    expect(spans[0]?.textContent).toBe('A')
    expect(spans[1]?.textContent).toBe('B')
    expect(spans[2]?.textContent).toBe('0')
  })

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

    const { container, rerender } = render(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    let boxes = container.querySelectorAll('.MuiBox-root')
    expect(boxes.length).toBe(1)

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

    rerender(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    boxes = container.querySelectorAll('.MuiBox-root')
    expect(boxes.length).toBe(2)
  })

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

    const { container, rerender } = render(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    expect(container.firstChild).toBeTruthy()

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

    rerender(
      <Row id='test-row'>
        <div>Content</div>
      </Row>,
    )

    expect(container.firstChild).toBeNull()
  })

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

    const { container } = render(
      <Row id='test-row'>{({ index }) => <div>Item {index}</div>}</Row>,
    )

    expect(container.textContent).toContain('Item 0')
  })

  test('handles many data items', () => {
    const data = Array.from({ length: 10 }, (_, i) => ({ value: i }))
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data,
    })

    const { container } = render(
      <Row id='test-row'>
        {({ index }) => <div className='item'>Item {index}</div>}
      </Row>,
    )

    const items = container.querySelectorAll('.item')
    expect(items.length).toBe(10)
  })

  test('passes only index in render prop', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }],
    })

    render(
      <Row id='test-row'>
        {(props) => {
          // Check that only index is passed
          expect(Object.keys(props)).toEqual(['index'])
          expect(typeof props.index).toBe('number')
          return <div>Content</div>
        }}
      </Row>,
    )
  })

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

    const { container } = render(
      <Row id='test-row'>
        <div>
          <span>Nested</span>
          <strong>Content</strong>
        </div>
      </Row>,
    )

    expect(container.querySelector('span')).toBeTruthy()
    expect(container.querySelector('strong')).toBeTruthy()
  })

  test('render prop can access external variables', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [{ value: 100 }, { value: 200 }],
    })

    const externalValue = 'External'

    const { container } = render(
      <Row id='test-row'>
        {({ index }) => (
          <div>
            {externalValue} {index}
          </div>
        )}
      </Row>,
    )

    expect(container.textContent).toContain('External 0')
    expect(container.textContent).toContain('External 1')
  })

  test('handles data array with different value types', () => {
    useWidgetStore.getState().setWidget<FormulaWidgetState>('test-row', {
      type: 'formula',
      data: [
        { value: 0 },
        { value: -100 },
        { value: 123.456 },
        { value: 1000000 },
      ],
    })

    const { container } = render(
      <Row id='test-row'>
        {({ index }) => <div className='item'>Item {index}</div>}
      </Row>,
    )

    const items = container.querySelectorAll('.item')
    expect(items.length).toBe(4)
  })
})
