import * as React from 'react'
import type { StoryObj, Meta } from '@storybook/react-webpack5'
import { GridEditorComboboxMulti } from '.'
import { Grid } from '../../grids'
import { GridCellChips } from '../../components'
import { PlusCircle } from '@planview/pv-icons'
import type { CellEditorParams, GridConfirmPayload } from '../../types'
import type { InputType } from '@storybook/csf'

const hideControl: InputType = { control: false }

export default {
    title: 'pv-grid/Components/Editors/GridEditorComboboxMulti',
    component: GridEditorComboboxMulti,
    parameters: {
        controls: {
            exclude: ['label', 'mode', 'rowId', 'columnId'],
        },
    },
    argTypes: {
        columnId: hideControl,
        rowId: hideControl,
        tabIndex: hideControl,
        value: hideControl,
        icon: {
            options: ['no icon', 'with custom icon'],
            mapping: {
                'no icon': undefined,
                'with custom icon': <PlusCircle />,
            },
            control: {
                type: 'radio',
            },
        },
        options: {
            control: false,
        },
    },
} satisfies Meta<typeof GridEditorComboboxMulti>

const tags = [
    'urgent',
    'important',
    'phone',
    'office',
    'errands',
    'low priority',
    'fun',
]

type TagRow = {
    id: string
    tags: string[]
}

function TagComboboxEditor(props: CellEditorParams<TagRow>): React.JSX.Element {
    const tagOptions = tags.map((t) => ({ value: t, label: t }))
    const currentTags = props.value as string[]

    return (
        <GridEditorComboboxMulti
            {...props}
            clearable={false}
            value={currentTags.map(
                (t) => tagOptions.find((tagOpt) => t === tagOpt.value)!
            )}
            options={tagOptions}
        />
    )
}

export const Default: StoryObj<typeof GridEditorComboboxMulti<TagRow>> = {
    render: function Component(args) {
        const [rows, setRows] = React.useState<TagRow[]>([
            { id: '1', tags: ['urgent', 'phone'] },
            { id: '2', tags: ['office'] },
            { id: '3', tags: ['errands', 'low priority'] },
        ])

        /* This is a storybook concern so its intentionally left out of code examples */
        const MappedComponent = React.useCallback(
            (props: CellEditorParams<TagRow>) => (
                <TagComboboxEditor {...props} {...args} />
            ),
            [args]
        )

        return (
            <Grid
                selectionMode="none"
                columns={[
                    {
                        id: 'tags',
                        label: 'Combobox Multi Editor',
                        sortable: false,
                        width: 300,
                        cell: {
                            editable: true,
                            Renderer(props) {
                                return <GridCellChips {...props} />
                            },
                            Editor: MappedComponent,
                        },
                    },
                ]}
                rows={rows}
                onCellChange={(
                    confirm: GridConfirmPayload<
                        TagRow,
                        'tags',
                        [{ value: string }]
                    >
                ) => {
                    setRows((r) =>
                        r.map((row) => {
                            if (row.id === confirm.rowId) {
                                return {
                                    ...row,
                                    tags: confirm.nextValue.map(
                                        (co) => co.value
                                    ),
                                }
                            }
                            return row
                        })
                    )
                }}
            />
        )
    },
}

Default.parameters = {
    docs: {
        source: {
            code: `
const tags = [
    'urgent',
    'important',
    'phone',
    'office',
    'errands',
    'low priority',
    'fun',
]

type TagRow = {
    id: string
    tags: string[]
}

function TagComboboxEditor(props: CellEditorParams<TagRow>): React.JSX.Element {
    const tagOptions = tags.map((t) => ({ value: t, label: t }))
    const currentTags = props.value as string[]

    return (
        <GridEditorComboboxMulti
            {...props}
            clearable={false}
            value={currentTags.map(
                (t) => tagOptions.find((tagOpt) => t === tagOpt.value)!
            )}
            options={tagOptions}
        />
    )
}

export const Default: StoryObj<typeof GridEditorComboboxMulti> = {
    render: function Component(args) {
        const [rows, setRows] = React.useState<TagRow[]>([
            { id: '1', tags: ['urgent', 'phone'] },
            { id: '2', tags: ['office'] },
            { id: '3', tags: ['errands', 'low priority'] },
        ])

        return (
            <Grid
                selectionMode="none"
                columns={[
                    {
                        id: 'tags',
                        label: 'Combobox Multi Editor',
                        sortable: false,
                        width: 300,
                        cell: {
                            editable: true,
                            Renderer(props) {
                                return <GridCellChips {...props} />
                            },
                            Editor: TagComboboxEditor,
                        },
                    },
                ]}
                rows={rows}
                onCellChange={(
                    confirm: GridConfirmPayload<
                        TagRow,
                        'tags',
                        [{ value: string }]
                    >
                ) => {
                    setRows((r) =>
                        r.map((row) => {
                            if (row.id === confirm.rowId) {
                                return {
                                    ...row,
                                    tags: confirm.nextValue.map(
                                        (co) => co.value
                                    ),
                                }
                            }
                            return row
                        })
                    )
                }}
            />
        )
    },
}
`,
        },
    },
}
