import { IconButton, Paper, useMediaQuery, useTheme } from '@mui/material'
import type { BasemapsUIProps } from './types'
import { useEffect, useRef, useState, type JSX } from 'react'
import { styles } from './styles'
import deepmerge from 'deepmerge'
import { DEFAULT_BASEMAPS_LABELS } from './const'
import { Header } from './header'
import { GroupWrapper } from './group-wrapper'
import { Group } from './group'
import { ResponsiveDrawer } from '../responsive-drawer/responsive-drawer'
import { Tooltip } from '../tooltip/tooltip'

const EMPTY_OPTIONS: BasemapsUIProps['options'] = []

/**
 * Provides an interactive basemap selector with responsive drawer, grouping support, and customizable positioning.
 *
 * @remarks
 * This is an uncontrolled component focused on UI presentation. Typically used with the `BasemapsControls` HOC from `@carto/ps-react-maps` for automatic state management.
 *
 * @example
 * ```tsx
 * <BasemapsControls mapId={mapId}>
 *   {({ basemap, setBasemap }) => (
 *     <BasemapsUI
 *       options={basemapOptions}
 *       selected={basemap}
 *       onChange={setBasemap}
 *       position="bottom-right"
 *     />
 *   )}
 * </BasemapsControls>
 * ```
 */
export function BasemapsUI({
  options = EMPTY_OPTIONS,
  labels: _labels,
  position = 'bottom-right',
  selected = null,
  onChange,
  TooltipProps,
}: BasemapsUIProps): JSX.Element {
  const [toggleRef, setToggleRef] = useState<HTMLButtonElement | null>(null)
  const [isOpen, setIsOpen] = useState(false)
  const timeoutRef = useRef<NodeJS.Timeout | null>(null)
  const [timer, setTimer] = useState<number | null>(null)
  const theme = useTheme()
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'))
  const labels = deepmerge(DEFAULT_BASEMAPS_LABELS, _labels ?? {})

  const optionSelected = options.find((option) => option.id === selected)

  const groups = Object.groupBy(options, (option) => option.group ?? 'default')

  const groupCount = Object.keys(groups).length

  const handleClose = () => {
    setToggleRef(null)
    setIsOpen(false)
  }

  useEffect(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current)
    }

    if (!timer) {
      return
    }

    timeoutRef.current = setTimeout(() => {
      handleClose()
      return
    }, timer)

    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current)
      }
    }
  }, [timer])

  const handleMouseOver = () => {
    setTimer(null)
  }
  const handleMouseLeave = () => {
    setTimer(400)
  }

  return (
    <Paper>
      <Tooltip title={labels.toggle.title} placement='right' {...TooltipProps}>
        <IconButton
          sx={styles.toggle}
          onClick={(e) => {
            setToggleRef(e.currentTarget as HTMLButtonElement)
            setIsOpen(true)
          }}
        >
          <img
            src={optionSelected?.icon}
            alt={optionSelected?.label ?? 'Basemap'}
          />
        </IconButton>
      </Tooltip>

      <ResponsiveDrawer
        ref={toggleRef}
        slotProps={{
          paper: {
            sx: {
              ...styles.root,
              transform: `translate3d(${position.endsWith('right') ? '-8px' : '8px'}, ${
                position.startsWith('bottom') ? '-4px' : '4px'
              }, 0) !important`,
            },
            onMouseOver: handleMouseOver,
            onMouseLeave: handleMouseLeave,
          },
        }}
        collapsed={!isOpen}
        position={position}
        isMobile={isMobile}
        onChangeCollapsed={() => handleClose()}
      >
        <Header
          isMobile={isMobile}
          labels={labels.header}
          onChangeCollapsed={() => handleClose()}
        />
        {Object.entries(groups).map(([group, values]) => (
          <GroupWrapper
            key={group}
            title={group + ' ' + labels.header.title}
            collapsed={groupCount < 2}
          >
            <Group
              values={values!}
              selected={selected}
              onChange={(e) => {
                handleClose()
                onChange(e)
              }}
            />
          </GroupWrapper>
        ))}
      </ResponsiveDrawer>
    </Paper>
  )
}
