import React from 'react'
import { SpreadsheetGrid } from '.'
import { render, snapshot, within } from '../../utils/test-utils'
import type { Column } from '../../types'
import userEvent from '@testing-library/user-event'

type Record = {
    id: string
    week1: number
    week2: number
    week3: number
}

const columns: Column<Record>[] = [
    { id: 'id', label: 'ID', width: 100 },
    { id: 'week1', label: 'Week 1', width: 100 },
    { id: 'week2', label: 'Week 2', width: 100 },
    { id: 'week3', label: 'Week 3', width: 100 },
]

const rows: Record[] = [
    { id: '1', week1: 10, week2: 20, week3: 30 },
    { id: '2', week1: 15, week2: 25, week3: 35 },
    { id: '3', week1: 20, week2: 30, week3: 40 },
]

describe('SpreadsheetGrid', () => {
    describe('snapshots', () => {
        snapshot(
            'should render empty',
            <SpreadsheetGrid columns={[]} rows={[]} />
        )

        snapshot(
            'should render empty',
            <SpreadsheetGrid columns={columns} rows={rows} />
        )
    })

    describe('range selection', () => {
        it('should show the grid is multi-selectable', () => {
            const { getByRole } = render(
                <SpreadsheetGrid columns={columns} rows={rows} />
            )

            expect(getByRole('grid')).toHaveAttribute(
                'aria-multiselectable',
                'true'
            )
        })

        it('should not show that rows are selectable', () => {
            const { getAllByRole } = render(
                <SpreadsheetGrid columns={columns} rows={rows} />
            )

            getAllByRole('row').forEach((row) => {
                expect(row).not.toHaveAttribute('aria-selected')
            })
        })

        it('should show the grid cells are selectable', () => {
            const { getAllByRole } = render(
                <SpreadsheetGrid columns={columns} rows={rows} />
            )

            getAllByRole('gridcell').forEach((cell) => {
                expect(cell).toHaveAttribute('aria-selected', 'false')
            })
        })

        it('should show selected cells as selected', () => {
            const { getAllByRole } = render(
                <SpreadsheetGrid
                    columns={columns}
                    rows={rows}
                    rangeSelection={{
                        from: { rowId: '1', columnId: 'week2' },
                        to: { rowId: '2', columnId: 'week3' },
                    }}
                />
            )

            const allRows = getAllByRole('row')

            const firstRowSelected = within(allRows[1])
                .getAllByRole('gridcell')
                .map((cell) => cell.getAttribute('aria-selected'))
            const secondRowSelected = within(allRows[2])
                .getAllByRole('gridcell')
                .map((cell) => cell.getAttribute('aria-selected'))
            const thirdRowSelected = within(allRows[3])
                .getAllByRole('gridcell')
                .map((cell) => cell.getAttribute('aria-selected'))

            expect(firstRowSelected).toEqual(['false', 'false', 'true', 'true'])
            expect(secondRowSelected).toEqual([
                'false',
                'false',
                'true',
                'true',
            ])
            expect(thirdRowSelected).toEqual([
                'false',
                'false',
                'false',
                'false',
            ])
        })

        it('should call onRangeSelectionChange when range selection changes (keyboard)', async () => {
            const onRangeSelectionChange = jest.fn()
            const { getAllByRole } = render(
                <SpreadsheetGrid
                    columns={columns}
                    rows={rows}
                    onRangeSelectionChange={onRangeSelectionChange}
                    rangeSelection={{
                        from: { rowId: '1', columnId: 'week1' },
                        to: { rowId: '1', columnId: 'week1' },
                    }}
                />
            )

            const allRows = getAllByRole('row')

            const firstRowSelected = within(allRows[1]).getAllByRole('gridcell')

            await userEvent.click(firstRowSelected[1])

            await userEvent.keyboard('{Shift>}{ArrowDown}{/Shift}')

            expect(onRangeSelectionChange).toHaveBeenCalledWith(
                {
                    from: { rowId: '1', columnId: 'week1' },
                    to: { rowId: '2', columnId: 'week1' },
                },
                {
                    columnIds: ['week1'],
                    rowIds: ['1', '2'],
                }
            )
        })
    })
})
