import React from 'react'
import {
    useClickOutside,
    text,
    spacingPx,
    states,
    useEscapeListener,
} from '@planview/pv-utilities'
import { Radio } from '@planview/pv-uikit'
import styled from 'styled-components'
import type { CellEditorParams, GridRowData } from '../types'
import { useGridColumn } from '../context/grid-context'
import { useGridEditor } from '../context/grid-editor-context'

const StyledRadio = styled(Radio)`
    * {
        outline: none;
    }
`

const CCell = styled.div<{
    $focusVisible: boolean
}>`
    ${text.regular};
    height: 100%;
    width: 100%;
    padding: 0 ${spacingPx.small};
    display: flex;
    flex-direction: row;
    align-items: center;
    min-width: 0;
    overflow: hidden;
    outline: none;
    ${(props) => states.focus({ focusVisible: props.$focusVisible })}
`

export const GridEditorRadio = <TDataModel extends GridRowData>({
    columnId,
    rowId,
    tabIndex,
    value,
    mode,
    onCancel,
    onConfirm,
}: CellEditorParams<TDataModel>) => {
    const ref = React.useRef<HTMLInputElement>(null)

    const column = useGridColumn(columnId)
    const columnLabel = column?.data?.label

    const { editable } = useGridEditor()

    const readOnly = !editable

    const handleOnClickOutside = React.useCallback(() => {
        if (mode === 'editing') {
            onCancel()
        }
    }, [onCancel, mode])

    useClickOutside(ref, handleOnClickOutside)

    React.useEffect(() => {
        if (mode === 'editing') {
            ref.current?.focus()
        }
    }, [mode])

    const handleClick = React.useCallback<React.MouseEventHandler>(
        (e) => e.stopPropagation(),
        []
    )

    const handleEscape = React.useCallback(() => {
        onCancel()
    }, [onCancel])

    useEscapeListener({
        onEscape: handleEscape,
        enabled: mode === 'editing',
        stack: true,
    })

    const onKeyDown = React.useCallback<React.KeyboardEventHandler>(
        (e) => {
            if (mode === 'navigation') {
                return
            }

            if (e.key === 'Tab') {
                e.stopPropagation()
                e.preventDefault()
                onConfirm(value, {
                    continueEditing: e.shiftKey ? 'previous' : 'next',
                })
                return
            }

            if (
                e.key === 'ArrowUp' ||
                e.key === 'ArrowDown' ||
                e.key === 'ArrowLeft' ||
                e.key === 'ArrowRight'
            ) {
                e.preventDefault()
                e.stopPropagation()
            }
        },
        [onConfirm, mode, value]
    )

    const handleChange = React.useCallback(() => {
        onConfirm(true, {
            continueEditing: 'current',
        })
    }, [onConfirm])

    const disabledProps = React.useMemo(
        () =>
            readOnly
                ? {
                      role: 'radio' as const,
                      tabIndex,
                      'aria-disabled': true,
                      'aria-checked': !!value,
                      'aria-label': columnLabel,
                  }
                : {},
        [columnLabel, readOnly, tabIndex, value]
    )

    return (
        <CCell {...disabledProps} $focusVisible={mode === 'editing'}>
            <StyledRadio
                aria-hidden={readOnly ? true : undefined}
                disabled={readOnly}
                ref={ref}
                tabIndex={tabIndex}
                selected={!!value}
                name={String(columnId)}
                value={String(rowId)}
                onClick={handleClick}
                onKeyDown={onKeyDown}
                onChange={handleChange}
                aria-label={columnLabel}
            />
        </CCell>
    )
}
