import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import PropTypes from 'prop-types'

const ActionHandler = forwardRef(
  (
    {
      children,
      actions = {},
      actionParam = 'action',
      clearAfterExecute = true,
      onAction,
      loading = true
    },
    ref
  ) => {
    const location = useLocation()
    const navigate = useNavigate()
    const action = new URLSearchParams(location.search).get(actionParam)

    // Ref to track last executed action
    const lastExecutedAction = useRef(null)

    // Method to add action as URL param
    const callAction = (actionName) => {
      const searchParams = new URLSearchParams(location.search)
      searchParams.set(actionParam, actionName)
      const newSearch = searchParams.toString()
      const newPath = location.pathname + (newSearch ? `?${newSearch}` : '')
      navigate(newPath, { replace: true })
    }

    // Method to clear current action from URL
    const clearAction = () => {
      const searchParams = new URLSearchParams(location.search)
      searchParams.delete(actionParam)
      const newSearch = searchParams.toString()
      const newPath = location.pathname + (newSearch ? `?${newSearch}` : '')
      navigate(newPath, { replace: true })
    }

    // Execute action and clear from URL
    useEffect(() => {
      if (
        loading == false &&
        action &&
        actions[action] &&
        lastExecutedAction.current !== action
      ) {
        // Execute the action
        const result = actions[action]()

        // Mark this action as executed
        lastExecutedAction.current = action
        // Call optional callback
        if (onAction) {
          onAction(action, result)
        }
        // Clear action from URL if requested and result is true
        if (clearAfterExecute && result == true) {
          const searchParams = new URLSearchParams(location.search)
          searchParams.delete(actionParam)
          const newSearch = searchParams.toString()
          const newPath = location.pathname + (newSearch ? `?${newSearch}` : '')
          navigate(newPath, { replace: true })
        }
      } else if (!action) {
        // Reset lastExecutedAction if no action is present
        lastExecutedAction.current = null
      }
    }, [
      loading,
      action,
      actions,
      actionParam,
      clearAfterExecute,
      onAction,
      location.pathname,
      location.search,
      navigate
    ])

    useImperativeHandle(ref, () => ({
      callAction,
      clearAction
    }))

    // Return null as this is a utility component
    return children
  }
)

ActionHandler.displayName = 'ActionHandler'

ActionHandler.propTypes = {
  children: PropTypes.oneOf([PropTypes.func, PropTypes.object]),
  actions: PropTypes.objectOf(PropTypes.func),
  actionParam: PropTypes.string,
  clearAfterExecute: PropTypes.bool,
  onAction: PropTypes.func,
  loading: PropTypes.bool
}

export default ActionHandler
