import PropTypes from 'prop-types'
import { createElement, useContext } from 'react'
import { Flex, Alert, Button, Dropdown } from 'antd'
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon'
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
import XMarkIcon from '../../Icons/XMarkIcon'
import { getModelByName } from '../../../database/ObjectModels'
import { useNavigate } from 'react-router-dom'
import ActionsIcon from '../../Icons/ActionsIcon'
import { ApiServerContext } from '../context/ApiServerContext'

const AlertsDisplay = ({
  object,
  objectType,
  showDismiss = true,
  showActions = true
}) => {
  const alerts = object?.alerts ?? []
  const objectId = object?._id
  const getAlertType = (type, priority) => {
    if (type === 'error' || priority === '9') return 'error'
    if (type === 'warning' || priority === '8') return 'warning'
    return 'info'
  }

  const model = objectType ? getModelByName(objectType) : null
  const navigate = useNavigate()
  const { updateObject } = useContext(ApiServerContext)

  const handleDismissAlert = (alertId) => {
    const updatedAlerts = alerts.filter((a) => a._id !== alertId)
    updateObject(objectId, objectType, { alerts: updatedAlerts })
  }
  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 objectActions = model?.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(objectActions, 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(objectId))
        } else {
          console.warn('No action found for key:', key)
        }
      }
    }

    return (
      <Alert
        key={`${alert.createdAt}-${index}-${alert._id}`}
        message={alert.message}
        style={{ padding: '4px 5px 4px 10px', minHeight: '35px' }}
        type={getAlertType(alert.type, alert.priority)}
        icon={getAlertIcon(alert.type, alert.priority)}
        showIcon
        closable={false}
        onClose={() => {}}
        action={
          <Flex gap='1px'>
            {showActions && filteredActions.length >= 0 && (
              <Dropdown menu={menu} on>
                <Button
                  size='small'
                  type='text'
                  style={{ marginLeft: '5px' }}
                  icon={
                    <ActionsIcon
                      style={{ fontSize: '12px', marginBottom: '3.5px' }}
                    />
                  }
                />
              </Dropdown>
            )}
            {showDismiss && alert.canDismiss && (
              <Button
                size='small'
                type='text'
                style={{ marginLeft: '5px' }}
                onClick={() => handleDismissAlert(alert._id)}
                icon={
                  <XMarkIcon
                    style={{
                      fontSize: '10px',
                      marginBottom: '5px',
                      marginLeft: '0.5px'
                    }}
                  />
                }
              />
            )}
          </Flex>
        }
      />
    )
  })

  return (
    <Flex gap='small' style={{ width: '100%' }} vertical align='stretch'>
      {alertElements}
    </Flex>
  )
}

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

export default AlertsDisplay
