import React from 'react'
import { Grid } from '.'
import type { UseGridReturn } from '../../hooks'
import { createGrid, useGrid } from '../../hooks'
import { render } from '../../utils/test-utils'
import type { GridRowDropInfo } from '../../types'

jest.mock('../../hooks', () => {
    const actual = jest.requireActual('../../hooks')
    return {
        ...actual,
        useGrid: jest.fn(),
    }
})

describe('Grid event binding', () => {
    let grid: UseGridReturn

    beforeEach(async () => {
        grid = createGrid()
        jest.mocked(useGrid).mockReturnValue(grid)
    })

    describe('event binding', () => {
        describe('rowDrag.onDrop binding to onRowDrop', () => {
            it('should clean up subscriptions when changing function', () => {
                const onDrop = jest.fn()

                // Using two different function references to test
                // cleanup of subscription
                const onDrop1 = (info: GridRowDropInfo) => onDrop(info)
                const onDrop2 = (info: GridRowDropInfo) => onDrop(info)

                const { rerender } = render(
                    <Grid
                        columns={[]}
                        rows={[]}
                        rowDrag={{ onDrop: onDrop1 }}
                    />
                )

                rerender(
                    <Grid
                        columns={[]}
                        rows={[]}
                        rowDrag={{ onDrop: onDrop2 }}
                    />
                )

                grid.events.emit('onRowDrop', {
                    draggedRowIds: [],
                    draggedRows: [],
                    targetIndex: null,
                    targetParent: null,
                    targetParentId: null,
                    resultIds: null,
                    droppedAfterId: null,
                })

                expect(onDrop).toHaveBeenCalledTimes(1)
                expect(onDrop).toHaveBeenCalledWith({
                    draggedRowIds: [],
                    draggedRows: [],
                    targetIndex: null,
                    targetParent: null,
                    targetParentId: null,
                    resultIds: null,
                    droppedAfterId: null,
                })
            })
        })
    })
})
