import * as React from 'react'
import type {
    CellEditorParams,
    EditorConfirmPayload,
    GridRowData,
} from '../../types'
import type {
    ComboboxCloseReason,
    ComboboxOption,
    ComboboxProps,
} from '@planview/pv-uikit'
import { cleanPropForSpread } from './utils'
import { StyledCombobox, Wrapper } from './styles'

export type GridEditorComboboxProps<TDataModel extends GridRowData> = Omit<
    CellEditorParams<TDataModel>,
    'value' | 'onConfirm'
> &
    Omit<
        ComboboxProps,
        | 'multiSelectable'
        | 'defaultValue'
        | 'onChange'
        | 'defaultOpen'
        | 'inputMode'
        | 'required'
        | 'value'
        | 'onRemove'
        | 'onSelect'
        | 'disabled'
        | 'readOnly'
        | 'onClose'
        | 'onOpen'
        | 'onFocus'
        | 'onBlur'
    > & {
        /** value */
        value?: ComboboxOption | null
        /**
         * confirm callback
         */
        onConfirm: (
            value?: ComboboxOption | null,
            payload?: EditorConfirmPayload
        ) => void
    }

export const GridEditorCombobox = <TDataModel extends GridRowData>({
    value,
    onCancel,
    onConfirm,
    options,
    label = '',
    ...rest
}: GridEditorComboboxProps<TDataModel>) => {
    const wrapperRef = React.useRef<HTMLDivElement | null>(null)
    const valueRef = React.useRef(value)

    React.useEffect(() => {
        valueRef.current = value
    }, [value])

    const handleChange = React.useCallback((opt: ComboboxOption | null) => {
        valueRef.current = opt
    }, [])

    const handleInputKeyDown = React.useCallback(
        (ev: React.KeyboardEvent<HTMLElement>) => {
            if (ev.key === 'Tab') {
                ev.preventDefault()
                ev.stopPropagation()
                onConfirm(valueRef.current, {
                    continueEditing: ev.shiftKey ? 'previous' : 'next',
                })
            }
        },
        [onConfirm]
    )

    const handleClose = React.useCallback(
        (reason: ComboboxCloseReason) => {
            if (reason === 'confirm_click' || reason === 'confirm_enter') {
                onConfirm(valueRef.current)
            } else if (!reason.includes('tab')) {
                onCancel()
            }
        },
        [onCancel, onConfirm]
    )

    React.useEffect(() => {
        const el = wrapperRef.current
        if (el) {
            const input = el.querySelector('input')
            input?.focus()
            input?.select()
        }
    }, [])

    return (
        <Wrapper ref={wrapperRef} onKeyDown={handleInputKeyDown}>
            <StyledCombobox
                {...cleanPropForSpread(rest)}
                label={label}
                options={options}
                defaultOpen
                onClose={handleClose}
                multiSelectable={false}
                onChange={handleChange}
                value={value}
            />
        </Wrapper>
    )
}
