/* eslint-disable react-native-a11y/has-valid-accessibility-role */
import React from 'react'
import PropTypes from 'prop-types'
import { View, StyleSheet, Platform } from 'react-native'
import { withLinkRouter } from '../utils/withLinkRouter'
import { variantProp } from '../utils/props/variantProp'
import { copyPropTypes } from '../utils/props/copyPropTypes'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { ExpandCollapsePanel } from '../ExpandCollapse/ExpandCollapsePanel'
import { ListboxItem } from './ListboxItem'
import { useListboxContext } from './ListboxContext'
import { GroupControl } from './GroupControl'
import { SecondLevelHeader } from './SecondLevelHeader'
import { dictionary as defaultDictionary } from './dictionary'

const styles = StyleSheet.create({
  groupWrapper: {
    margin: 0,
    padding: 0,
    overflow: 'visible'
  },
  list: {
    margin: 0,
    padding: 0
  },
  secondLevelContainer: {
    margin: 0,
    padding: 0,
    width: '100%',
    display: 'flex',
    flexDirection: 'column'
  },
  secondLevelList: {
    margin: 0,
    padding: 0,
    width: '100%'
  }
})

const getAccessibilityRole = () =>
  Platform.select({
    ios: 'listitem',
    android: 'none',
    web: 'listitem'
  })

const selectSecondLevelContainerStyles = ({ secondLevelHeaderBackgroundColor }) => ({
  backgroundColor: secondLevelHeaderBackgroundColor
})

export const ListboxGroup = React.forwardRef(
  (
    {
      id,
      label,
      items,
      LinkRouter,
      linkRouterProps,
      expandProps,
      onLastItemBlur,
      nextItemRef,
      prevItemRef,
      copy = 'en',
      dictionary = defaultDictionary,
      variant = {},
      tokens = {},
      onClose
    },
    ref
  ) => {
    const { selectedId, activeSecondLevelGroup, setActiveSecondLevelGroup } = useListboxContext()
    const [secondLevelOpen, setSecondLevelOpen] = React.useState(false)
    const isSecondLevel = variant?.secondLevel === true
    const listboxTokens = useThemeTokens('Listbox', variant, tokens)
    const groupId = id ?? label

    const handleGroupClick = React.useCallback(() => {
      if (isSecondLevel) {
        setSecondLevelOpen(true)
        setActiveSecondLevelGroup(groupId)
      }
    }, [isSecondLevel, groupId, setActiveSecondLevelGroup])

    const handleBackClick = React.useCallback(() => {
      setSecondLevelOpen(false)
      setActiveSecondLevelGroup(null)
    }, [setActiveSecondLevelGroup])

    const handleCloseClick = React.useCallback(() => {
      setSecondLevelOpen(false)
      setActiveSecondLevelGroup(null)
      if (onClose) {
        onClose()
      }
    }, [setActiveSecondLevelGroup, onClose])

    if (isSecondLevel && activeSecondLevelGroup && activeSecondLevelGroup !== groupId) {
      return null
    }

    if (isSecondLevel && secondLevelOpen) {
      return (
        <View
          style={[styles.secondLevelContainer, selectSecondLevelContainerStyles(listboxTokens)]}
        >
          <SecondLevelHeader
            label={label}
            onBack={handleBackClick}
            onClose={handleCloseClick}
            copy={copy}
            dictionary={dictionary}
            variant={variant}
            tokens={tokens}
          />
          <View style={styles.secondLevelList}>
            {items &&
              items.map((item, index) => {
                return (
                  <ListboxItem
                    key={item.label}
                    id={item.id ?? item.label}
                    {...item}
                    selected={
                      (item.id && item.id === selectedId) ||
                      (item.label && item.label === selectedId)
                    }
                    isChild={false}
                    LinkRouter={LinkRouter}
                    linkRouterProps={linkRouterProps}
                    variant={variant}
                    tokens={tokens}
                    {...(index === 0 && { prevItemRef })}
                    {...(index === items.length - 1 && { nextItemRef })}
                    {...(index === items.length - 1 && { onBlur: onLastItemBlur })}
                  />
                )
              })}
          </View>
        </View>
      )
    }

    // TODO: implement keyboard navigation via refs for grouped items separately here
    return (
      <View id="test" style={styles.groupWrapper} accessibilityRole={getAccessibilityRole()}>
        <ExpandCollapsePanel
          panelId={id ?? label}
          controlTokens={{
            icon: null,
            paddingLeft: 0,
            paddingRight: 0,
            paddingTop: 0,
            paddingBottom: 0,
            backgroundColor: 'transparent',
            borderColor: 'transparent',
            textLine: 'none',
            borderWidth: 0
          }}
          // TODO refactor
          // eslint-disable-next-line react/no-unstable-nested-components
          control={(controlProps) => (
            <GroupControl id={id ?? label} {...controlProps} label={label} variant={variant} />
          )}
          {...expandProps}
          {...(isSecondLevel && { open: false })}
          {...(isSecondLevel && { onPress: handleGroupClick })}
          tokens={{
            contentPaddingLeft: 0,
            contentPaddingRight: 0,
            contentPaddingTop: 0,
            contentPaddingBottom: 0,
            borderColor: 'transparent',
            borderRadius: 0,
            borderWidth: 0,
            marginBottom: 0,
            contentPanelBackgroundColor: 'transparent'
          }}
          controlRef={ref}
        >
          {!isSecondLevel && (
            <View style={styles.list}>
              {items.map((item, index) => {
                return (
                  <ListboxItem
                    key={item.label}
                    id={item.id ?? item.label}
                    {...item}
                    selected={
                      (item.id && item.id === selectedId) ||
                      (item.label && item.label === selectedId)
                    }
                    isChild
                    LinkRouter={LinkRouter}
                    linkRouterProps={linkRouterProps}
                    variant={variant}
                    tokens={tokens}
                    {...(index === 0 && { prevItemRef })}
                    {...(index === items.length - 1 && { nextItemRef })}
                    {...(index === items.length - 1 && { onBlur: onLastItemBlur })}
                  />
                )
              })}
            </View>
          )}
        </ExpandCollapsePanel>
      </View>
    )
  }
)
ListboxGroup.displayName = 'ListboxGroup'

ListboxGroup.propTypes = {
  ...withLinkRouter.propTypes,
  /**
   * Unique identifier for the group
   */
  id: PropTypes.string,
  label: PropTypes.string,
  items: PropTypes.arrayOf(
    PropTypes.shape({
      href: PropTypes.string,
      label: PropTypes.string,
      current: PropTypes.bool
    })
  ),
  expandProps: PropTypes.object,
  nextItemRef: PropTypes.object,
  prevItemRef: PropTypes.object,
  /**
   * Use this callback to redirect the focus after it leaves the last item of the group.
   */
  onLastItemBlur: PropTypes.func,
  /**
   * Select English or French copy
   */
  copy: copyPropTypes,
  /**
   * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
   */
  dictionary: PropTypes.shape({
    en: PropTypes.shape({
      closeMenu: PropTypes.string.isRequired
    }),
    fr: PropTypes.shape({
      closeMenu: PropTypes.string.isRequired
    })
  }),
  /**
   * Variant configuration for secondLevel behavior
   */
  variant: variantProp.propType,
  /**
   * Custom tokens
   */
  tokens: PropTypes.object,
  /**
   * Callback when the menu is closed
   */
  onClose: PropTypes.func
}
