import * as React from 'react'
import type { StoryFn, Meta } from '@storybook/react-webpack5'
import { SpreadsheetGrid } from '.'
import type {
    Column,
    GridProps,
    GridActionsMenuFullProps,
    GridConfirmPayload,
} from '../../types'
import { GridCellDefault } from '../../components'
import {
    ListItem,
    ListItemDivider,
    ListItemInfo,
    Menu,
} from '@planview/pv-uikit'
import { Copy, Cut, Trash } from '@planview/pv-icons'
import { GridEditorInputNumeric } from '../../editors'

export default {
    title: 'pv-grid/Components/SpreadsheetGrid (Experimental)',
    id: 'pv-grid/Components/SpreadsheetGrid',
    component: SpreadsheetGrid,
    parameters: {
        badges: ['intl'],
    },
    args: {
        rowHeight: 'medium',
        filterMode: 'default',
        sortMode: 'internal',
    },
    argTypes: {
        onRangeCopy: {
            table: {
                category: 'Bulk editing',
            },
        },
        onBulkCellChange: {
            table: {
                category: 'Bulk editing',
            },
        },
        loading: {
            control: { type: 'radio' },
            options: [false, true, 3, 6],
            table: {
                category: 'Status',
            },
        },
        emptyContent: {
            table: {
                category: 'Status',
            },
        },
        columns: {
            control: false,
        },
        columnGroups: {
            control: { type: 'radio' },
            options: ['without groups', 'with groups'],
            mapping: {
                'without groups': [],
                'with groups': [
                    {
                        id: 'top-group',
                        label: 'Group',
                        children: ['title', 'price'],
                    },
                ],
            },
        },
        rows: {
            control: false,
        },
        ref: {
            control: false,
            description:
                'This will return an api for interacting with the grid externally.',
            table: {
                category: 'Advanced',
            },
        },
        defaultSort: {
            control: false,
            table: {
                category: 'Sorting',
            },
        },
        sort: {
            control: false,
            table: {
                category: 'Sorting',
            },
        },
        sortMode: {
            table: {
                category: 'Sorting',
            },
        },
        multiColumnSort: {
            table: {
                category: 'Sorting',
            },
        },
        onSortChange: {
            table: {
                category: 'Sorting',
            },
        },
        rangeSelection: {
            table: {
                category: 'Selection',
            },
        },
        onRangeSelectionChange: {
            table: {
                category: 'Selection',
            },
        },
        filter: {
            table: {
                category: 'Filtering',
            },
        },
        filterMode: {
            table: {
                category: 'Filtering',
            },
        },
        filteredIds: {
            control: { type: 'radio' },
            options: ['not filtered', 'filtered', 'no matches'],
            mapping: {
                'not filtered': undefined,
                filtered: ['1002'],
                'no matches': [],
            },
            table: {
                category: 'Filtering',
            },
        },
        preferencesAdapter: {
            control: false,
            table: {
                category: 'Advanced',
            },
        },
        expandedRows: {
            control: false,
            table: {
                category: 'Tree',
            },
        },
        onExpandedRowsChange: {
            table: {
                category: 'Tree',
            },
        },
        actionsMenu: {
            control: { type: 'radio' },
            options: ['no actions menu', 'actions menu', 'actions menu async'],
            mapping: {
                'no actions menu': undefined,
                'actions menu': () => (
                    <>
                        <ListItem icon={<Cut />} label="Cut" />
                        <ListItem icon={<Copy />} label="Copy" />
                        <ListItemDivider />
                        <ListItem icon={<Trash />} label="Delete" />
                    </>
                ),
                'actions menu async': {
                    Menu({ row, menuProps }: GridActionsMenuFullProps<Row>) {
                        const [loading, setLoading] = React.useState(true)

                        React.useEffect(() => {
                            const t = setTimeout(() => setLoading(false), 500)
                            return () => clearTimeout(t)
                        }, [])

                        return (
                            <Menu {...menuProps} loading={loading}>
                                <ListItemInfo>{row.title}</ListItemInfo>
                                <ListItemDivider />
                                <ListItem icon={<Cut />} label="Cut" />
                                <ListItem icon={<Copy />} label="Copy" />
                                <ListItemDivider />
                                <ListItem icon={<Trash />} label="Delete" />
                            </Menu>
                        )
                    },
                },
            },
            table: {
                category: 'Context Menu',
            },
        },
        enableColumnVisibilityMenu: {
            control: { type: 'boolean' },
            table: {
                category: 'Context Menu',
            },
        },
        rowDrag: {
            control: false,
            table: {
                category: 'Drag and Drop',
            },
        },
        onCellChange: {
            control: false,
            table: {
                category: 'Editing',
            },
        },
    },
} satisfies Meta<typeof SpreadsheetGrid>

type Row = {
    id: string
    title: string
    price?: number
}

const rows = [
    { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99 },
    {
        id: '1002',
        title: 'Twenty Thousand Leagues Under the Sea',
        price: 35.65,
    },
    { id: '1003', title: 'Around the World In Eighty Days', price: 29.98 },
]

const currencyFormatter = new Intl.NumberFormat(undefined, {
    style: 'currency',
    currency: 'USD',
})

export const Default: StoryFn<GridProps<Row>> = ({
    columns: _columns,
    rows: _rows,
    ...rest
}) => {
    const columns = React.useMemo<Column<Row>[]>(
        () => [
            {
                id: 'id',
                label: 'ID',
                width: 100,
            },
            {
                id: 'title',
                label: 'Title',
                width: 400,
            },
            {
                id: 'price',
                label: 'Price',
                width: 200,
                header: {
                    align: 'right',
                },
                cell: {
                    label: ({ value }: { value: number }) =>
                        currencyFormatter.format(value),
                    Renderer: ({ label, tabIndex }) => (
                        <GridCellDefault
                            numeric
                            tabIndex={tabIndex}
                            label={label}
                        />
                    ),
                },
            },
        ],
        []
    )

    return <SpreadsheetGrid columns={columns} rows={rows} {...rest} />
}

Default.parameters = {
    docs: {
        source: {
            code: `
type Book = {
    id: number
    title: string
    price: number
}

const rows = React.useMemo<Book[]>(() => [
    { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99 },
    {
        id: '1002',
        title: 'Twenty Thousand Leagues Under the Sea',
        price: 35.65,
    },
    { id: '1003', title: 'Around the World In Eighty Days', price: 29.98 },
], [])

const columns = React.useMemo<Column<Book>[]>(
    () => [
        {
            id: 'id',
            label: 'ID',
            width: 100,
        },
        {
            id: 'title',
            label: 'Title',
            width: 400,
        },
        {
            id: 'price',
            label: 'Price',
            width: 200,
            header: {
                align: 'right',
            },
            cell: {
                label: ({ value }: { value: number }) =>
                    currencyFormatter.format(value),
                Renderer: ({ label, tabIndex }) => (
                    <GridCellDefault numeric tabIndex={tabIndex} label={label} />
                ),
            },
        },
    ],
    []
)

return <SpreadsheetGrid columns={columns} rows={rows} {...rest} />
            `,
        },
    },
}

export const Editable: StoryFn<GridProps<Row>> = ({
    columns: _columns,
    rows: _rows,
    ...rest
}) => {
    const [data, setData] = React.useState(rows)

    const columns = React.useMemo<Column<Row>[]>(
        () => [
            {
                id: 'id',
                label: 'ID',
                width: 100,
            },
            {
                id: 'title',
                label: 'Title',
                width: 400,
                cell: {
                    editable: true,
                },
            },
            {
                id: 'price',
                label: 'Price',
                width: 200,
                header: {
                    align: 'right',
                },
                cell: {
                    editable: true,
                    label: ({ value }: { value: number }) =>
                        currencyFormatter.format(value),
                    Renderer: ({ label, tabIndex }) => (
                        <GridCellDefault
                            numeric
                            tabIndex={tabIndex}
                            label={label}
                        />
                    ),
                    Editor: GridEditorInputNumeric,
                },
            },
        ],
        []
    )

    return (
        <SpreadsheetGrid
            columns={columns}
            rows={data}
            onCellChange={(payload: GridConfirmPayload<Row>) => {
                setData((prev) =>
                    prev.map((r) =>
                        r.id === payload.rowId
                            ? { ...r, [payload.columnId]: payload.nextValue }
                            : r
                    )
                )
            }}
            {...rest}
        />
    )
}

Editable.parameters = {
    docs: {
        source: {
            code: `
type Book = {
    id: number
    title: string
    price: number
}

const rows = React.useMemo<Book[]>(() => [
    { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99 },
    {
        id: '1002',
        title: 'Twenty Thousand Leagues Under the Sea',
        price: 35.65,
    },
    { id: '1003', title: 'Around the World In Eighty Days', price: 29.98 },
], [])

const columns = React.useMemo<Column<Book>[]>(
    () => [
        {
            id: 'id',
            label: 'ID',
            width: 100,
        },
        {
            id: 'title',
            label: 'Title',
            width: 400,
        },
        {
            id: 'price',
            label: 'Price',
            width: 200,
            header: {
                align: 'right',
            },
            cell: {
                label: ({ value }: { value: number }) =>
                    currencyFormatter.format(value),
                Renderer: ({ label, tabIndex }) => (
                    <GridCellDefault numeric tabIndex={tabIndex} label={label} />
                ),
            },
        },
    ],
    []
)

return <SpreadsheetGrid columns={columns} rows={rows} {...rest} />
            `,
        },
    },
}
