import React, { useEffect, useRef } from 'react'
import PropTypes from 'prop-types'
import { Popover, Typography } from 'antd'

// Utility to parse shortcut string like 'cmd+shift+p' or 'ctrl+s'
function parseShortcut(shortcut) {
  const parts = shortcut.toLowerCase().split('+')
  return {
    meta: parts.includes('cmd') || parts.includes('meta') || false,
    ctrl: parts.includes('ctrl') || parts.includes('control') || false,
    alt: parts.includes('alt') || parts.includes('option') || false,
    shift: parts.includes('shift') || false,
    key: parts.find(
      (p) =>
        !['cmd', 'meta', 'ctrl', 'control', 'alt', 'option', 'shift'].includes(
          p
        )
    )[0]
  }
}

const { Text } = Typography

const KeyboardShortcut = ({ shortcut, children, hint, onTrigger }) => {
  const childRef = useRef()
  const shortcutObj = parseShortcut(shortcut)
  let pressedKeys = new Set()

  // Helper to get the set of keys required for the shortcut
  function getShortcutKeySet(shortcutObj) {
    const keys = []
    if (shortcutObj.meta) keys.push('Meta')
    if (shortcutObj.ctrl) keys.push('Control')
    if (shortcutObj.alt) keys.push('Alt')
    if (shortcutObj.shift) keys.push('Shift')
    // shortcutObj.code is like 'keyp', so extract the last char
    if (shortcutObj.key) {
      keys.push('Key' + shortcutObj.key.toUpperCase())
    }
    return new Set(keys)
  }

  const shortcutKeySet = getShortcutKeySet(shortcutObj)

  useEffect(() => {
    pressedKeys = new Set()
    const handleKeyDown = (event) => {
      if (
        event.key === 'Meta' ||
        event.key === 'Control' ||
        event.key === 'Alt' ||
        event.key === 'Shift'
      ) {
        pressedKeys.add(event.key)
      } else if (event.code && event.code.startsWith('Key')) {
        pressedKeys.add(event.code)
      }
      if (
        shortcutKeySet.size &&
        [...shortcutKeySet].every((k) => pressedKeys.has(k))
      ) {
        if (typeof onTrigger === 'function') {
          onTrigger(event)
        }
        event.preventDefault()
      }
    }
    const handleKeyUp = (event) => {
      if (
        event.key === 'Meta' ||
        event.key === 'Control' ||
        event.key === 'Alt' ||
        event.key === 'Shift'
      ) {
        pressedKeys.delete(event.key)
      } else if (event.code && event.code.startsWith('Key')) {
        pressedKeys.delete(event.key.toUpperCase())
      }
    }
    window.addEventListener('keydown', handleKeyDown)
    window.addEventListener('keyup', handleKeyUp)
    return () => {
      window.removeEventListener('keydown', handleKeyDown)
      window.removeEventListener('keyup', handleKeyUp)
    }
  }, [shortcut, shortcutObj, onTrigger])

  // Clone the child to attach a ref
  const element = React.cloneElement(children, { ref: childRef })

  if (hint) {
    return (
      <Popover
        content={
          <Text keyboard className='keyboard-shortcut-tooltip'>
            {hint}
          </Text>
        }
        arrow={false}
      >
        {element}
      </Popover>
    )
  }
  return element
}

KeyboardShortcut.propTypes = {
  shortcut: PropTypes.string.isRequired, // e.g. 'cmd+shift+p'
  onTrigger: PropTypes.func.isRequired,
  children: PropTypes.element.isRequired,
  hint: PropTypes.string // Optional, e.g. '⌘ ⇧ P'
}

export default KeyboardShortcut
