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

import { Box } from '../box'
import { styled, useStyleConfig, vui } from '../core'
import { List } from '../list'
import { cs, filterUndefined, isArray, isReactText, vuiColorToRGBA } from '../utils'
import { useTreeContext } from './context'
import { TreeItemProps } from './tree.types'
import TreeIcon from './treeIcon'
import TreeText from './treeText'

/*@formatter:off*/
export const TreeItemBase = styled.liBox`
  display: flex;
  flex-direction: column;
  transition-duration: fast;
  width: 100%;
`
/*@formatter:on*/

/**
 * Displays a tree item with text and optional icons. Can be shown as selected.
 */
export const TreeItem = vui<'li', TreeItemProps>((props, ref) => {
  const mergedProps = { ...useTreeContext(), ...props }

  const {
    activeItemId,
    activeItemIndex,
    children,
    center,
    centerH,
    centerV = true,
    className,
    iconCollapse = 'falMinus',
    isCollapsed,
    disabled,
    iconExpand = 'falPlus',
    id,
    items,
    isActive,
    isFirstLevel,
    isTruncated,
    key,
    onClickTreeItem,
    onToggle,
    propagatedPL,
    plUnit = 26,
    text,
    ...rest
  } = mergedProps
  const styles = useStyleConfig('Tree', useTreeContext())
  const { activeBg, bg, color, h, hoverBg, hoverColor, p, px, py, selectedBg, ...itemStyles } = styles.item

  const [collapsedInternal, setIsCollapsedInternal] = useState<boolean>(false)

  const innerBoxPl = propagatedPL || 0
  const innerListPl = innerBoxPl + (plUnit || 0)

  useEffect(() => {
    setIsCollapsedInternal(!!isCollapsed)
  }, [isCollapsed])

  const toggle = (e: Event) => {
    if (!disabled) {
      onToggle?.({ id, collapsed: !collapsedInternal })
      setIsCollapsedInternal(!collapsedInternal)
    }

    const target = e.target as HTMLDivElement
    const active = target?.closest('.vui-tree')?.getElementsByClassName('vui-treeItem-active')[0] as HTMLDivElement
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions
    active ? (active.style.backgroundColor = 'transparent') : null

    onClickTreeItem?.(id)

    // Avoids triggering parent's onClick
    e.stopPropagation()
  }

  const hoverTreeItem = (e: Event, type: string) => {
    const target = e.target as HTMLDivElement

    let parentDiv = undefined

    if (target.classList.contains('vui-treeItem-permanent')) {
      parentDiv = target
    } else {
      const parentLi = target.closest('.vui-treeItem')
      parentDiv = parentLi?.getElementsByClassName('vui-treeItem-permanent')[0] as HTMLDivElement
    }

    const isDivActive = parentDiv.classList.contains('vui-treeItem-active') ? true : false

    // translate the list-item style over to the div
    if (parentDiv.classList.contains('vui-treeItem-permanent')) {
      // is it a fist level item?
      if (parentDiv.classList.contains('vui-treeItem-firstLevel')) {
        if (type === 'over') {
          parentDiv.style.backgroundColor = vuiColorToRGBA(styles?.firstLevelItem?.hoverBg || 'transparent')
        }

        if (type === 'out') {
          parentDiv.style.backgroundColor = isDivActive
            ? vuiColorToRGBA(styles?.firstLevelItem?.activeBg || 'transparent')
            : vuiColorToRGBA(styles?.firstLevelItem?.bg || 'transparent')
        }
      } else {
        // it is NOT first level
        if (type === 'over') {
          parentDiv.style.backgroundColor = vuiColorToRGBA(styles?.item?.hoverBg || 'transparent')
        }
        if (type === 'out') {
          parentDiv.style.backgroundColor = isDivActive
            ? vuiColorToRGBA(styles?.item?.activeBg || 'transparent')
            : vuiColorToRGBA(styles?.item?.bg || 'transparent')
        }
      }
    } else {
      e.preventDefault()
    }

    e.stopPropagation()
  }

  const isCollapsable = (isArray(children) && children.length > 0) || (isArray(items) && items.length > 0)
  const isActiveInternal = (!activeItemIndex && isActive) || activeItemIndex === id

  let textMl = items && items?.length > 0 ? 0 : 1.5
  if (!isCollapsable) {
    textMl += 3.8
  }

  const aliasedProps = filterUndefined({
    'aria-expanded': isCollapsable ? !collapsedInternal : undefined,
    role: 'treeitem',
  })

  // hoverBg cannot be styled directly from theme, it has to be JS manipulated because of event propagation
  return (
    <TreeItemBase
      className={cs('vui-treeItem', isFirstLevel ? 'vui-treeItem-firstLevel' : '', className)}
      color={isFirstLevel ? styles?.firstLevelItem?.color : color}
      h={collapsedInternal ? h : isCollapsable ? 'auto' : h}
      id={id.toString()}
      m={0}
      onClick={!disabled ? (e: Event) => toggle(e) : undefined}
      onMouseOut={!disabled ? (e: Event) => hoverTreeItem(e, 'out') : undefined}
      onMouseOver={!disabled ? (e: Event) => hoverTreeItem(e, 'over') : undefined}
      p={0}
      propagatedPL={propagatedPL}
      ref={ref}
      w={1}
      {...itemStyles}
      bg={
        isFirstLevel
          ? isActiveInternal
            ? styles?.firstLevelItem?.activeBg
            : styles?.firstLevelItem?.bg
          : isActiveInternal
            ? styles?.item?.activeBg
            : bg
      }
      hoverBg={undefined}
      {...aliasedProps}
      {...rest}
    >
      <>
        <Box
          centerV
          className={cs(
            'vui-treeItem-permanent',
            isActiveInternal ? 'vui-treeItem-active' : '',
            isFirstLevel ? 'vui-treeItem-firstLevel' : '',
          )}
          fontWeight={isActiveInternal ? '600' : '500'}
          pl={`${innerBoxPl}px`}
        >
          {items && items?.length > 0 && (
            <>
              {collapsedInternal ? <TreeIcon mx={1.5} name={iconExpand} /> : <TreeIcon mx={1.5} name={iconCollapse} />}
            </>
          )}
          {isReactText(text) ? <TreeText ml={textMl} {...{ isTruncated, text }} /> : text}
        </Box>

        {isCollapsable && !collapsedInternal && (
          <List role="tree" w={1}>
            {children ??
              (isArray<TreeItemProps>(items)
                ? items.map(({ key, propagatedPL, ...props }, index) => {
                    return (
                      <TreeItem
                        activeItemIndex={activeItemIndex}
                        iconCollapse={iconCollapse}
                        iconExpand={iconExpand}
                        key={key ?? index}
                        onClickTreeItem={onClickTreeItem}
                        propagatedPL={innerListPl}
                        {...props}
                      />
                    )
                  })
                : items)}
          </List>
        )}
      </>
    </TreeItemBase>
  )
})

TreeItem.displayName = 'TreeItem'

export default TreeItem
