import React from 'react'
import PropTypes from 'prop-types'
import { Platform, Pressable, StyleSheet, Text, View } from 'react-native'
import { useThemeTokensCallback } from '../ThemeProvider/useThemeTokens'
import { applyTextStyles } from '../ThemeProvider/utils/styles'
import { useTheme } from '../ThemeProvider/useTheme'
import { a11yProps } from '../utils/props/a11yProps'
import { getTokensPropType, selectTokens } from '../utils/props/tokens'
import { resolvePressableTokens } from '../utils/pressability'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { useOverlaidPosition } from '../utils/useOverlaidPosition'
import { useCopy } from '../utils/useCopy'
import { variantProp } from '../utils/props/variantProp'
import { viewProps } from '../utils/props/viewProps'
import { withLinkRouter } from '../utils/withLinkRouter'
import { useViewport } from '../ViewportProvider/useViewport'
import { Icon } from '../Icon/Icon'
import { Listbox } from '../Listbox/Listbox'
import { ListboxOverlay } from '../Listbox/ListboxOverlay'
import { dictionary } from './dictionary'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])

const selectButtonContentStyles = ({
  backgroundColor,
  borderColor,
  borderWidth,
  borderRadius,
  paddingHorizontal,
  paddingVertical,
  marginHorizontal,
  marginVertical
}) => ({
  backgroundColor,
  borderColor,
  borderWidth,
  borderRadius,
  paddingHorizontal,
  paddingVertical,
  marginLeft: marginHorizontal,
  marginRight: marginHorizontal,
  marginTop: marginVertical,
  marginBottom: marginVertical
})

/**
 * TabsDropdown renders a dropdown version of tabs for mobile/tablet viewports.
 * It shows the currently selected tab as a button that opens a dropdown menu
 * containing all available tabs.
 *
 * This is rendered automatically by `Tabs` on mobile viewports and when variant
 * is dropdown and isn't intended to be used directly.
 */
export const TabsDropdown = React.forwardRef(
  (
    {
      itemTokens,
      variant,
      value,
      onChange,
      items = [],
      LinkRouter,
      linkRouterProps,
      accessibilityRole = 'button',
      copy = 'en',
      dictionary: customDictionary = dictionary,
      ...rest
    },
    ref
  ) => {
    const { themeOptions } = useTheme()
    const viewport = useViewport()
    const [isOpen, setIsOpen] = React.useState(false)

    const getTokens = useThemeTokensCallback('TabsItem', itemTokens, { viewport, ...variant })

    const selectedItem =
      items.find((item) => {
        const itemId = item.id ?? item.label
        return value === itemId
      }) || items[0]

    const { overlaidPosition, sourceRef, targetRef, onTargetLayout, isReady } = useOverlaidPosition(
      {
        isShown: isOpen,
        offsets: { vertical: 4 },
        align: { top: 'bottom', left: 'left' }
      }
    )

    const handleToggle = () => setIsOpen((prev) => !prev)
    const handleClose = () => setIsOpen(false)

    const handleItemSelect = (item, event) => {
      const itemId = item.id ?? item.label
      setIsOpen(false)

      if (onChange) onChange(itemId, event)
      if (item.onPress) item.onPress(event)
    }

    const listboxItems = items.map((item) => ({
      ...item,
      onPress: (event) => handleItemSelect(item, event)
    }))

    const isSelected = Boolean(selectedItem && value)
    const getCopy = useCopy({ dictionary: customDictionary, copy })

    const selectedProps = selectProps({
      accessibilityRole,
      ...rest
    })

    return (
      <View ref={ref} style={styles.container}>
        <Pressable
          ref={sourceRef}
          onPress={handleToggle}
          {...selectedProps}
          style={styles.pressable}
        >
          {(pressableState) => {
            // Use resolvePressableTokens like TabBarItem does for proper state handling
            const resolvedTokens = resolvePressableTokens(getTokens, pressableState, {
              viewport,
              expanded: isOpen,
              selected: isSelected
            })

            const textStyles = applyTextStyles({
              ...selectTokens('Typography', resolvedTokens),
              themeOptions
            })

            // Get dropdown icons from resolved tokens
            const dropdownIcon = isOpen
              ? resolvedTokens.dropdownIconExpanded
              : resolvedTokens.dropdownIcon

            return (
              <View style={[styles.buttonContent, selectButtonContentStyles(resolvedTokens)]}>
                <Text style={textStyles}>{selectedItem?.label || getCopy('selectTab')}</Text>
                {dropdownIcon && (
                  <Icon
                    icon={dropdownIcon}
                    variant={{ size: 'micro' }}
                    tokens={{
                      color: textStyles.color
                    }}
                  />
                )}
              </View>
            )
          }}
        </Pressable>

        {isOpen && (
          <ListboxOverlay
            overlaidPosition={overlaidPosition}
            maxWidth={400}
            minWidth={200}
            isReady={isReady}
            onLayout={onTargetLayout}
          >
            <Listbox
              items={listboxItems}
              firstItemRef={targetRef}
              parentRef={sourceRef}
              selectedId={value}
              onClose={handleClose}
              LinkRouter={LinkRouter}
              linkRouterProps={linkRouterProps}
            />
          </ListboxOverlay>
        )}
      </View>
    )
  }
)

TabsDropdown.displayName = 'TabsDropdown'

const dictionaryContentShape = PropTypes.shape({
  selectTab: PropTypes.string.isRequired
})

TabsDropdown.propTypes = {
  ...selectedSystemPropTypes,
  ...withLinkRouter.propTypes,
  /**
   * Array of tab items
   */
  items: PropTypes.arrayOf(
    PropTypes.shape({
      ...withLinkRouter.propTypes,
      /** URL to navigate to when the tab is pressed */
      href: PropTypes.string,
      /** Display text for the tab */
      label: PropTypes.string,
      /** Unique identifier for the tab */
      id: PropTypes.string,
      /** Reference to the tab element */
      ref: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
      /** Custom render function for the tab content */
      render: PropTypes.func
    })
  ),
  /**
   * Current selected tab id
   */
  value: PropTypes.string,
  /**
   * Callback for when the selected tab changes
   */
  onChange: PropTypes.func,
  /**
   * Custom tokens for the main Tabs container
   */
  tokens: getTokensPropType('Tabs'),
  /**
   * Custom tokens for `TabsItem`
   */
  itemTokens: getTokensPropType('TabsItem'),
  /**
   * Visual and behavioral variants for the tabs dropdown
   */
  variant: variantProp.propType,
  /**
   * Select English or French copy for the accessible labels.
   * You may also pass in a custom dictionary object.
   */
  copy: PropTypes.oneOfType([PropTypes.oneOf(['en', 'fr']), dictionaryContentShape]),
  /**
   * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
   */
  dictionary: PropTypes.shape({
    en: dictionaryContentShape,
    fr: dictionaryContentShape
  })
}

const styles = StyleSheet.create({
  container: {
    position: 'relative',
    width: '100%'
  },
  pressable:
    Platform.OS === 'web'
      ? {
          outlineWidth: 0,
          outlineStyle: 'none',
          outlineColor: 'transparent'
        }
      : {},
  buttonContent: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    width: '100%',
    minHeight: 44
  }
})
