import React, { useEffect, useRef, useState } from 'react'

import Button from '../Button/Button'
import DropdownMenu from '../DropdownMenu/DropdownMenu'
import Icon from '../Icons/Icon'
import { type IconStringList } from '../Icons/Icon.models'
import Menu from '../Menu/Menu'
import { SideDrawer } from '../SideDrawer/SideDrawer'
import { useIsMobileView } from '../../hooks/useIsMobileView/useIsMobileView'
import styles from './_account_popover.module.scss'
import { c } from '../../translations/LibraryTranslationService'

export type AccountPopoverProps = {
  /** The name of the user */
  name: string
  /** The array of options to be displayed in the popover */
  options: {
    icon: IconStringList
    label: string
    callout: () => void
    hide?: boolean
    keepOpen?: boolean
  }[]
  /** Function to close the mobile drawer. This is kept as optional because it is not needed in LeftNavDesktop. */
  closeMobileDrawer?: () => void
  /** Function to close the Sidebar expanded state. This is kept as optional because it is not needed in LeftNavMobile. */
  closeSidebar?: (force?: boolean) => void
  /** Function to open the Sidebar expanded state. */
  openSidebar?: () => void
  /** There are 2 variations: collapsed and expanded. This prop determines when to show each. */
  expanded: boolean
  /** Shows whether LeftNavMobile is being rendered with this component */
  mobile?: boolean
  /** Optional prop to make username or email read only */
  disabled?: boolean
}

const AccountPopover = ({
  name,
  options,
  closeMobileDrawer,
  expanded,
  closeSidebar,
  openSidebar,
  mobile,
  disabled = false,
}: AccountPopoverProps): React.JSX.Element => {
  const [isDrawerOpen, setDrawerOpen] = useState(false)
  const isMobileView = useIsMobileView()
  const contentRef = useRef<HTMLDivElement>(null)

  // Create actions array that can be reused by both DropdownMenu and Menu
  const createActions = (
    setVisible?: React.Dispatch<React.SetStateAction<boolean>>,
  ) =>
    options
      .filter((option) => !option.hide)
      .map((option) => ({
        text: option.label,
        icon: option.icon,
        callout: () => {
          option.callout()
          if (!option.keepOpen || !mobile) {
            setVisible?.(false)
          }
          if (mobile && !option.keepOpen) {
            closeMobileDrawer?.()
          }
          // Always close sidebar in desktop mode (when closeSidebar is available)
          if (!isMobileView && closeSidebar) {
            closeSidebar(true) // Force close to override hover detection logic
          }
        },
      }))

  const PopoverOrDrawerContent = ({
    setVisible,
  }: {
    setVisible: React.Dispatch<React.SetStateAction<boolean>>
  }) => <AccountPopoverList actions={createActions(setVisible)} />

  const PopoverOrSidedrawerChildren = ({
    visible,
    setVisible,
  }: {
    visible: boolean
    setVisible: React.Dispatch<React.SetStateAction<boolean>>
  }) => {
    return (
      <div className={styles.popoverChildren} ref={contentRef}>
        <Button as='unstyled' onClick={() => setVisible(!visible)}>
          <Container
            name={name}
            expanded={!!expanded}
            openSidebar={openSidebar}
            disabled={disabled}
            visible={visible}
            setVisible={setVisible}
          />
        </Button>
      </div>
    )
  }
  return isMobileView ? (
    <>
      {PopoverOrSidedrawerChildren({
        visible: isDrawerOpen,
        setVisible: setDrawerOpen,
      })}
      <SideDrawer
        headerContent={c('account')}
        layerPosition={1}
        noGradient={true}
        contentClassName={styles.sideDrawer}
        isOpen={isDrawerOpen && !disabled}
        closeCallout={() => setDrawerOpen(false)}
      >
        {PopoverOrDrawerContent({ setVisible: setDrawerOpen })}
      </SideDrawer>
    </>
  ) : (
    <DropdownMenu
      key={expanded ? 'expanded' : 'collapsed'} // Force remount when sidebar state changes
      actions={createActions()}
      trigger={
        <Button as='unstyled'>
          <Container
            name={name}
            expanded={!!expanded}
            openSidebar={openSidebar}
            disabled={disabled}
            visible={false}
            setVisible={() => {}}
          />
        </Button>
      }
      popoverProps={{
        position: 'top',
        appendTo: contentRef.current,
      }}
    />
  )
}

export default AccountPopover

const AccountPopoverList = ({
  actions,
}: {
  actions: {
    text: string
    icon: IconStringList
    callout: () => void
  }[]
}) => {
  return <Menu actions={actions} />
}

const Container = ({
  name,
  expanded,
  openSidebar,
  disabled,
  visible,
  setVisible,
}: Pick<
  AccountPopoverProps,
  'name' | 'expanded' | 'openSidebar' | 'disabled'
> & {
  visible?: boolean
  setVisible?: React.Dispatch<React.SetStateAction<boolean>>
}) => {
  useEffect(() => {
    if (!expanded) {
      setVisible?.(false)
    }
  }, [expanded, setVisible])

  return (
    <div
      className={`${styles.popoverContainer} ${
        expanded ? styles.expandedContainer : ''
      } ${disabled ? styles.disabledCursor : ''}`}
      onMouseEnter={() => {
        !expanded && openSidebar?.()
      }}
    >
      <div
        className={`${styles.iconAndName} ${
          disabled && !expanded ? styles.maleUserIcon : ''
        }`}
        data-testid='account_popover_dropdown_container'
      >
        <Icon icon='maleUser' qaTestId='logout' />
        {expanded ? (
          <div className={styles.nameContainer}>
            <div className={`${styles.name} animated slideInLeft`}>{name}</div>
          </div>
        ) : null}
      </div>
      {!disabled ? (
        <Icon
          icon='carat'
          iconSize='8px'
          className={`${visible ? styles.rotate : ''} ${styles.carat}`}
        />
      ) : null}
    </div>
  )
}
