import { createElement, useContext } from 'react'
import { Dropdown, Button } from 'antd'
import { getModelByName } from '../../../database/ObjectModels'
import PropTypes from 'prop-types'
import { useNavigate, useLocation } from 'react-router-dom'
import { useActionsModal } from '../context/ActionsModalContext'
import KeyboardShortcut from './KeyboardShortcut'
import { AuthContext } from '../context/AuthContext'
import {
  buildActionUrl,
  stripPageActionParams
} from '../../../utils/modelActions'

// Recursively filter actions based on visibleActions
function filterActionsByVisibility(actions, visibleActions) {
  if (!visibleActions) return actions

  return actions.filter((action) => {
    if (action.type === 'divider') {
      return true // Always show dividers
    }

    const actionKey = action.key || action.name
    const isVisible = visibleActions[actionKey] !== false

    // If this action has children, filter them recursively
    if (action.children && Array.isArray(action.children)) {
      const filteredChildren = filterActionsByVisibility(
        action.children,
        visibleActions
      )
      action.children = filteredChildren
      // Show parent if it has visible children or if it's explicitly visible
      return (
        isVisible &&
        (filteredChildren.length > 0 || visibleActions[actionKey] === true)
      )
    }

    return isVisible
  })
}

function cleanDividers(items) {
  if (!Array.isArray(items) || items.length === 0) return []

  const cleaned = []

  for (const item of items) {
    if (!item) continue

    if (item.type === 'divider') {
      if (cleaned.length === 0) continue
      if (cleaned[cleaned.length - 1]?.type === 'divider') continue
      cleaned.push(item)
      continue
    }

    if (item.children && Array.isArray(item.children)) {
      const children = cleanDividers(item.children)
      if (children.length === 0) continue
      cleaned.push({ ...item, children })
      continue
    }

    cleaned.push(item)
  }

  if (cleaned[cleaned.length - 1]?.type === 'divider') {
    cleaned.pop()
  }

  return cleaned
}

function isSameActionUrl(action, actionUrl, currentUrl, pathname, search) {
  if (action.type === 'modal') {
    return actionUrl === currentUrl
  }
  // Compare the action URL to the current location with its action param
  // stripped. Default page actions (e.g. Info) match and stay hidden when
  // already on that page. Actions that set their own action param (edit,
  // cancelEdit, finishEdit, etc.) do not match and remain available —
  // visibility is controlled by action.visible (e.g. _isEditing).
  return actionUrl === stripPageActionParams(pathname, search)
}

// Recursively map actions to AntD Dropdown items
function mapActionsToMenuItems(
  actions,
  currentUrlWithActions,
  id,
  objectData,
  userProfile,
  model,
  pathname,
  search
) {
  return cleanDividers(
    actions.map((action) => {
      if (action.type === 'divider') {
        return { type: 'divider' }
      }
      const actionUrl = buildActionUrl(model, action, id, pathname, search)

      var disabled = isSameActionUrl(
        action,
        actionUrl,
        currentUrlWithActions,
        pathname,
        search
      )
      var visible = true

      if (action.disabled) {
        if (typeof action.disabled === 'function') {
          disabled = action.disabled({ ...objectData, _user: userProfile })
        } else {
          disabled = action.disabled
        }
      }

      if (action.visible) {
        if (typeof action.visible === 'function') {
          visible = action.visible(objectData)
        } else {
          visible = action.visible
        }
      }

      if (visible != true) {
        return null
      }

      const item = {
        key: action.key || action.name,
        label: action.label,
        danger: action?.danger || false,
        icon: action.icon ? createElement(action.icon) : undefined,
        disabled
      }
      if (action.children && Array.isArray(action.children)) {
        item.children = mapActionsToMenuItems(
          action.children,
          currentUrlWithActions,
          id,
          objectData,
          userProfile,
          model,
          pathname,
          search
        )
      }
      return item
    })
  )
}

const ObjectActions = ({
  type,
  id,
  objectData,
  disabled = false,
  buttonProps = {},
  visibleActions = {},
  ...dropdownProps
}) => {
  const model = getModelByName(type)
  const actions = model.actions || []
  const navigate = useNavigate()
  const location = useLocation()
  const { showActionsModal } = useActionsModal()
  const { userProfile } = useContext(AuthContext)

  // First filter by visibility, then by current URL
  const visibilityFilteredActions = filterActionsByVisibility(
    actions,
    visibleActions
  )

  const filteredActions = cleanDividers(
    visibilityFilteredActions.filter((action) => {
      if (action.type === 'divider') return true
      const actionUrl = buildActionUrl(
        model,
        action,
        id,
        location.pathname,
        location.search
      )
      return !isSameActionUrl(
        action,
        actionUrl,
        location.pathname + location.search,
        location.pathname,
        location.search
      )
    })
  )

  const currentUrlWithActions = location.pathname + location.search

  // Compose AntD Dropdown menu items
  const menu = {
    items: mapActionsToMenuItems(
      filteredActions,
      currentUrlWithActions,
      id,
      objectData,
      userProfile,
      model,
      location.pathname,
      location.search
    ),
    onClick: (info) => {
      // Find the action by key
      const findAction = (acts, key) => {
        for (const act of acts) {
          if ((act.key || act.name) === key) return act
          if (act.children) {
            const found = findAction(act.children, key)
            if (found) return found
          }
        }
        return null
      }
      const action = findAction(filteredActions, info.key)
      if (action) {
        navigate(
          buildActionUrl(model, action, id, location.pathname, location.search)
        )
      }
    }
  }

  return (
    <KeyboardShortcut
      shortcut='alt+a'
      onTrigger={() => showActionsModal(id, type, objectData)}
    >
      <Dropdown menu={menu} {...dropdownProps}>
        <Button
          {...buttonProps}
          disabled={disabled || filteredActions.length === 0}
          onClick={() => showActionsModal(id, type, objectData)}
        >
          Actions
        </Button>
      </Dropdown>
    </KeyboardShortcut>
  )
}

ObjectActions.propTypes = {
  type: PropTypes.string.isRequired,
  objectData: PropTypes.object.isRequired,
  id: PropTypes.string.isRequired,
  disabled: PropTypes.bool,
  buttonProps: PropTypes.object,
  buttonLabel: PropTypes.string,
  visibleActions: PropTypes.object
}

export default ObjectActions
