import PropTypes from 'prop-types'
import { createElement } from 'react'
import { Flex, Alert, Button, Dropdown, Popover } from 'antd'
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon'
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
import { CaretDownOutlined } from '@ant-design/icons'

import { useMediaQuery } from 'react-responsive'
import { getModelByName } from '../../../database/ObjectModels'
import { useNavigate } from 'react-router-dom'

const AlertsDisplay = ({
  alerts = [],
  printerId,
  showDismiss = true,
  showActions = true
}) => {
  const isMobile = useMediaQuery({ maxWidth: 768 })
  const getAlertType = (type, priority) => {
    if (type === 'error' || priority === '9') return 'error'
    if (type === 'warning' || priority === '8') return 'warning'
    return 'info'
  }

  const printerModel = getModelByName('printer')
  const navigate = useNavigate()
  const getAlertIcon = (type, priority) => {
    if (type === 'error' || priority === '9') return <ExclamationOctagonIcon />
    if (type === 'warning' || priority === '8')
      return <ExclamationOctagonIcon />
    return <InfoCircleIcon />
  }

  // Recursively filter the printer model actions by a set of allowed action keys
  const filterActionsByKeys = (actions, allowedKeys) => {
    if (!Array.isArray(actions)) return []

    const filtered = actions
      .map((action) => {
        if (action.type === 'divider') {
          return { type: 'divider' }
        }

        const actionKey = action.key || action.name
        let children = []

        if (Array.isArray(action.children)) {
          children = filterActionsByKeys(action.children, allowedKeys)
        }

        const isAllowed = actionKey && allowedKeys.has(actionKey)

        if (!isAllowed && children.length === 0) {
          return null
        }

        return {
          ...action,
          children
        }
      })
      .filter((action) => action !== null)

    // Clean up dividers: remove leading/trailing and consecutive dividers
    const cleaned = []
    for (const action of filtered) {
      if (action.type === 'divider') {
        if (cleaned.length === 0) continue
        if (cleaned[cleaned.length - 1].type === 'divider') continue
      }
      cleaned.push(action)
    }
    if (cleaned[cleaned.length - 1]?.type === 'divider') {
      cleaned.pop()
    }

    return cleaned
  }

  // Map filtered printer actions to AntD Dropdown menu items (including children)
  const mapActionsToMenuItems = (actions) => {
    if (!Array.isArray(actions)) return []

    return actions.map((action) => {
      if (action.type === 'divider') {
        return { type: 'divider' }
      }

      const item = {
        key: action.key || action.name,
        label: action.label,
        icon: action.icon ? createElement(action.icon) : undefined
      }

      if (Array.isArray(action.children) && action.children.length > 0) {
        item.children = mapActionsToMenuItems(action.children)
      }

      return item
    })
  }

  if (alerts.length == 0) {
    return null
  }

  const alertElements = alerts.map((alert, index) => {
    const printerActions = printerModel?.actions || []

    const alertActionKeys = Array.isArray(alert?.actions)
      ? alert.actions
          .map((action) =>
            typeof action === 'string'
              ? action
              : action?.key || action?.name || null
          )
          .filter((key) => key != null)
      : []

    const allowedKeys = new Set(alertActionKeys)
    const filteredActions = filterActionsByKeys(printerActions, allowedKeys)

    const findActionByKey = (actions, key) => {
      if (!Array.isArray(actions)) return null

      for (const action of actions) {
        if (action.type === 'divider') continue

        const actionKey = action.key || action.name
        if (actionKey === key) {
          return action
        }

        if (Array.isArray(action.children) && action.children.length > 0) {
          const found = findActionByKey(action.children, key)
          if (found) return found
        }
      }

      return null
    }

    const menu = {
      items: mapActionsToMenuItems(filteredActions),
      onClick: ({ key }) => {
        const action = findActionByKey(filteredActions, key)

        if (action?.url) {
          navigate(action.url(printerId))
        } else {
          console.warn('No action found for key:', key)
        }
      }
    }

    return (
      <Alert
        key={`${alert.createdAt}-${index}-${alert._id}`}
        message={alert.message}
        style={{ padding: '4px 10px 4px 8px' }}
        type={getAlertType(alert.type, alert.priority)}
        icon={getAlertIcon(alert.type, alert.priority)}
        showIcon
        closable={showDismiss && alert.canDismiss}
        onClose={() => {
          console.log('Closing alert:', alert._id)
        }}
        action={
          showActions ? (
            <Dropdown menu={menu} on>
              <Button size='small' type='text' style={{ marginLeft: '5px' }}>
                <CaretDownOutlined />
              </Button>
            </Dropdown>
          ) : null
        }
      />
    )
  })

  if (isMobile) {
    return (
      <Popover
        content={alertElements}
        trigger='hover'
        arrow={false}
        placement='bottom'
        classNames={{
          root: 'printer-alerts-display-popover'
        }}
      >
        <Button>Alerts</Button>
      </Popover>
    )
  }

  return <Flex gap='small'>{alertElements}</Flex>
}

AlertsDisplay.propTypes = {
  printerId: PropTypes.string.isRequired,
  showActions: PropTypes.bool.isRequired,
  showDismiss: PropTypes.bool.isRequired,
  alerts: PropTypes.arrayOf(
    PropTypes.shape({
      canDismiss: PropTypes.bool.isRequired,
      _id: PropTypes.string.isRequired,
      type: PropTypes.string.isRequired,
      createdAt: PropTypes.string.isRequired,
      updatedAt: PropTypes.string.isRequired,
      message: PropTypes.string,
      actions: PropTypes.arrayOf(PropTypes.string)
    })
  ).isRequired
}

export default AlertsDisplay
