import { useState, type MouseEvent } from 'react'
import {
  Box,
  Divider,
  IconButton,
  Menu,
  MenuItem,
  Typography,
} from '@mui/material'
import {
  ChecklistOutlined as ChecklistIcon,
  VisibilityOutlined as VisibilityIcon,
} from '@mui/icons-material'
import { Tooltip } from '../../../components/tooltip/tooltip'
import {
  getLegendStore,
  selectVisibleLayersGrouped,
  useLegendId,
  useLegendShallow,
  useLegendStore,
} from '../../stores'
import { useLegendConfig } from '../../provider'
import { styles } from './styles'

/** `key` ties section derivation to the visibility fingerprint subscription. */
function sectionsForKey(legendId: string, key: string) {
  void key
  return selectVisibleLayersGrouped(getLegendStore(legendId).getState())
}

/**
 * Panel checklist of visible layers — each entry hides its layer; the menu
 * closes when nothing remains to list.
 *
 * @experimental This API is new and may change in a future release.
 */
export function LegendVisibleLayers() {
  const id = useLegendId()
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
  // Fingerprint avoids opacity-driven re-renders (React Compiler would hoist stale useMemo).
  const visibleKey = useLegendStore(id, (s) =>
    selectVisibleLayersGrouped(s)
      .map(
        ({ group, layers }) =>
          `${group?.id ?? ''}\x1f${group?.label ?? ''}:${layers
            .map((l) => `${l.id}\x1f${l.name}`)
            .join(',')}`,
      )
      .join('|'),
  )
  const sections = sectionsForKey(id, visibleKey)
  const setVisibility = useLegendShallow(id, (s) => s.setVisibility)
  const { labels } = useLegendConfig()

  const count = sections.reduce((n, s) => n + s.layers.length, 0)
  // Derived close when count hits 0; clear anchor on exit so it can't reopen stale.
  const open = Boolean(anchorEl) && count > 0

  const handleOpen = (e: MouseEvent<HTMLElement>) =>
    setAnchorEl(e.currentTarget)
  const handleClose = () => setAnchorEl(null)

  return (
    <>
      <Tooltip title={labels.toggleEnabledLayers}>
        {/* Span: MUI Tooltip can't attach listeners to a disabled button. */}
        <Box component='span' sx={styles.triggerWrap}>
          <IconButton
            size='small'
            className={open ? 'active' : undefined}
            disabled={count === 0}
            onClick={handleOpen}
            aria-label={labels.enabledLayers}
            aria-haspopup='menu'
            aria-expanded={open}
          >
            <ChecklistIcon fontSize='small' />
          </IconButton>
        </Box>
      </Tooltip>
      <Menu
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        TransitionProps={{ onExited: handleClose }}
        // No list padding — sticky header sits flush (avoids scroll peek-through).
        MenuListProps={{ disablePadding: true }}
        slotProps={{ paper: { sx: styles.paper } }}
      >
        <Typography
          component='div'
          variant='caption'
          color='text.primary'
          sx={styles.stickyHeader}
        >
          {`${labels.enabledLayers} (${count})`}
        </Typography>
        {sections.flatMap((section, index) => [
          index > 0 ? (
            <Divider
              key={`divider-${section.group?.id ?? 'ungrouped'}`}
              sx={styles.divider}
            />
          ) : null,
          section.group ? (
            <Typography
              key={`caption-${section.group.id}`}
              variant='caption'
              fontWeight='medium'
              color='text.secondary'
              sx={styles.groupCaption}
            >
              {section.group.label}
            </Typography>
          ) : null,
          ...section.layers.map((layer) => (
            <MenuItem
              key={layer.id}
              disableRipple
              sx={styles.item}
              onClick={() => setVisibility(layer.id, false)}
            >
              <Typography variant='body2' sx={styles.itemName}>
                {layer.name}
              </Typography>
              <Tooltip title={labels.hideLayer}>
                <VisibilityIcon sx={styles.eye} />
              </Tooltip>
            </MenuItem>
          )),
        ])}
      </Menu>
    </>
  )
}
