import * as React from 'react'
import type { StoryFn, Meta } from '@storybook/react-webpack5'
import type { Column, GridApi, GridConfirmPayload } from '..'
import { GridEditorSwitch, Grid, GridCellDefault } from '..'
import { ButtonEmpty } from '@planview/pv-uikit'
import { Lock, PlusCircle, Trash } from '@planview/pv-icons'
import styled from 'styled-components'
import { theme, spacingPx } from '@planview/pv-utilities'

export default {
    title: 'pv-grid/Examples/Editable',
    tags: ['hidden'],
} satisfies Meta<any>

const PageWrapper = styled.div`
    max-width: 720px;
    width: 100%;
    margin: ${spacingPx.large} auto;
`

const Actions = styled.div`
    display: flex;
    flex-direction: row;
    gap: ${spacingPx.small};
`

type Metric = {
    id: string
    name: string
    abbreviation: string
    weight: number
    inverted: boolean
    question: string
}

const INITIAL: Metric[] = [
    {
        id: '1',
        name: 'Value',
        abbreviation: 'V',
        weight: 20,
        inverted: false,
        question: 'How valuable is this work?',
    },
    {
        id: '2',
        name: 'Time Criticality',
        abbreviation: 'TC',
        weight: 20,
        inverted: false,
        question: 'How critical is it to do this work now?',
    },
    {
        id: '3',
        name: 'Risk Reduction',
        abbreviation: 'RR',
        weight: 20,
        inverted: false,
        question: 'How much does this work reduce future risk?',
    },
    {
        id: '4',
        name: 'Effort',
        abbreviation: 'E',
        weight: 40,
        inverted: true,
        question: 'How much effort is involved in this work?',
    },
]

const COLUMN_DEFAULTS: Partial<Column<Metric>> = {
    sortable: false,
    resizable: false,
    movable: false,
    cell: {
        editable: true,
    },
}

export const CardScoring: StoryFn = () => {
    const [selection, setSelection] = React.useState<Set<string>>(new Set())
    const [metrics, setMetrics] = React.useState<Metric[]>(INITIAL)
    const gridRef = React.useRef<GridApi>(null)
    const canDelete = !!selection.size
    const canCreate = metrics.length < 6

    const handleDelete = React.useCallback(() => {
        setSelection(new Set())
        setMetrics((ms) => ms.filter((m) => !selection.has(m.id)))
    }, [selection])

    const handleAdd = React.useCallback(() => {
        const id = Math.floor(Math.random() * 10000).toString()
        setMetrics((m) => [
            ...m,
            {
                id,
                name: 'Untitled Metric',
                abbreviation: 'UM',
                weight: 1,
                inverted: false,
                question: 'Untitled question',
            },
        ])
        if (gridRef.current) {
            const api = gridRef.current
            setTimeout(() => {
                console.log('Start editing', id, 'name')
                api.edit.start({ columnId: 'name', rowId: id })
                api.focus.set(id, 'name', 'body')
            }, 0)
        }
    }, [])

    const handleCellChange = React.useCallback(
        (payload: GridConfirmPayload<Metric, keyof Metric>) => {
            setMetrics((_metrics) =>
                _metrics.map((metric) => {
                    if (metric.id === payload.rowId) {
                        if (payload.columnId === 'name') {
                            return {
                                ...metric,
                                name: payload.nextValue,
                                abbreviation: payload.nextValue
                                    ? payload.nextValue
                                          .split(' ')
                                          .map((v) => [...v][0].toUpperCase())
                                          .join('')
                                    : metric.abbreviation,
                            }
                        }

                        return {
                            ...metric,
                            [payload.columnId]: payload.nextValue,
                        }
                    }
                    return metric
                })
            )
        },
        []
    )
    return (
        <PageWrapper>
            <Actions>
                <ButtonEmpty
                    icon={<PlusCircle />}
                    disabled={!canCreate}
                    onClick={handleAdd}
                >
                    Add Metric
                </ButtonEmpty>
                <ButtonEmpty
                    icon={<Trash />}
                    disabled={!canDelete}
                    onClick={handleDelete}
                >
                    Delete Selected
                </ButtonEmpty>
            </Actions>
            <Grid
                ref={gridRef}
                selection={selection}
                onSelectionChange={setSelection}
                columns={React.useMemo<Column<Metric>[]>(
                    () => [
                        {
                            ...COLUMN_DEFAULTS,
                            id: 'name',
                            label: 'Name',
                            width: 172,
                        },
                        {
                            ...COLUMN_DEFAULTS,
                            id: 'abbreviation',
                            label: 'Abbreviation',
                            width: 90,
                        },
                        {
                            ...COLUMN_DEFAULTS,
                            id: 'weight',
                            label: 'Weight',
                            width: 70,
                            header: {
                                align: 'right',
                            },
                            cell: {
                                editable: true,
                                Renderer({ value, tabIndex }) {
                                    return (
                                        <GridCellDefault
                                            numeric
                                            tabIndex={tabIndex}
                                            label={value}
                                        />
                                    )
                                },
                            },
                        },
                        {
                            ...COLUMN_DEFAULTS,
                            id: 'inverted',
                            label: 'Inverted',
                            cell: {
                                editable: ({ row }) => row.id !== '2',
                                hybridEditor: true,
                                Renderer: ({ tabIndex }) => (
                                    <GridCellDefault
                                        tabIndex={tabIndex}
                                        icon={<Lock color={theme.iconNormal} />}
                                    />
                                ),
                                Editor: GridEditorSwitch,
                            },
                            width: 70,
                        },
                        {
                            ...COLUMN_DEFAULTS,
                            id: 'question',
                            label: 'Question / Definition',
                            width: 280,
                        },
                    ],
                    []
                )}
                rows={metrics}
                onCellChange={handleCellChange}
            />
        </PageWrapper>
    )
}

CardScoring.parameters = {
    docs: {
        source: {
            code: `
const [selection, setSelection] = React.useState<Set<string>>(new Set())
const [metrics, setMetrics] = React.useState<Metric[]>(INITIAL)
const gridRef = React.useRef<GridApi>(null)
const canDelete = !!selection.size
const canCreate = metrics.length < 6

const handleDelete = React.useCallback(() => {
    setSelection(new Set())
    setMetrics((ms) => ms.filter((m) => !selection.has(m.id)))
}, [selection])

const handleAdd = React.useCallback(() => {
    const id = Math.floor(Math.random() * 10000).toString()
    setMetrics((m) => [
        ...m,
        {
            id,
            name: 'Untitled Metric',
            abbreviation: 'UM',
            weight: 1,
            inverted: false,
            question: 'Untitled question',
        },
    ])
    if (gridRef.current) {
        const api = gridRef.current
        setTimeout(() => {
            console.log('Start editing', id, 'name')
            api.edit.start({ columnId: 'name', rowId: id })
            api.focus.set(id, 'name', 'body')
        }, 0)
    }
}, [])

const handleCellChange = React.useCallback(
    (payload: GridConfirmPayload<Metric, keyof Metric>) => {
        setMetrics((_metrics) =>
            _metrics.map((metric) => {
                if (metric.id === payload.rowId) {
                    if (payload.columnId === 'name') {
                        return {
                            ...metric,
                            name: payload.nextValue,
                            abbreviation: payload.nextValue
                                ? payload.nextValue
                                        .split(' ')
                                        .map((v) => [...v][0].toUpperCase())
                                        .join('')
                                : metric.abbreviation,
                        }
                    }

                    return {
                        ...metric,
                        [payload.columnId]: payload.nextValue,
                    }
                }
                return metric
            })
        )
    },
    []
)
return (
    <PageWrapper>
        <Actions>
            <ButtonEmpty
                icon={<PlusCircle />}
                disabled={!canCreate}
                onClick={handleAdd}
            >
                Add Metric
            </ButtonEmpty>
            <ButtonEmpty
                icon={<Trash />}
                disabled={!canDelete}
                onClick={handleDelete}
            >
                Delete Selected
            </ButtonEmpty>
        </Actions>
        <Grid
            ref={gridRef}
            selection={selection}
            onSelectionChange={setSelection}
            columns={React.useMemo<Column<Metric>[]>(
                () => [
                    {
                        ...COLUMN_DEFAULTS,
                        id: 'name',
                        label: 'Name',
                        width: 172,
                    },
                    {
                        ...COLUMN_DEFAULTS,
                        id: 'abbreviation',
                        label: 'Abbreviation',
                        width: 90,
                    },
                    {
                        ...COLUMN_DEFAULTS,
                        id: 'weight',
                        label: 'Weight',
                        width: 70,
                        header: {
                            align: 'right',
                        },
                        cell: {
                            editable: true,
                            Renderer({ value, tabIndex }) {
                                return (
                                    <GridCellDefault
                                        numeric
                                        tabIndex={tabIndex}
                                        label={value}
                                    />
                                )
                            },
                        },
                    },
                    {
                        ...COLUMN_DEFAULTS,
                        id: 'inverted',
                        label: 'Inverted',
                        cell: {
                            editable: ({ row }) => row.id !== '2',
                            hybridEditor: true,
                            Renderer: ({ tabIndex }) => (
                                <GridCellDefault
                                    tabIndex={tabIndex}
                                    icon={<Lock color={color.iconNormal} />}
                                />
                            ),
                            Editor: GridEditorSwitch,
                        },
                        width: 70,
                    },
                    {
                        ...COLUMN_DEFAULTS,
                        id: 'question',
                        label: 'Question / Definition',
                        width: 280,
                    },
                ],
                []
            )}
            rows={metrics}
            onCellChange={handleCellChange}
        />
    </PageWrapper>
)
            `,
        },
    },
}
