import type { ReactNode } from 'react'
import { Box, Collapse, Typography } from '@mui/material'
import { ExpandMore as ExpandMoreIcon } from '@mui/icons-material'
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'
import { SmartTooltip } from '../../../components/smart-tooltip/smart-tooltip'
import {
  selectGroupVisibility,
  selectLayersByGroup,
  useLegendId,
  useLegendShallow,
  useLegendStore,
} from '../../stores'
import { accordionKeyDown } from '../a11y'
import { LegendGroupContext } from '../contexts'
import { partitionLegendChildren } from '../legend-actions/legend-actions'
import { useLegendSortable } from '../legend-sortable/contexts'
import {
  SortableEntity,
  type SortableEntityRenderProps,
} from '../legend-sortable/sortable-entity'
import { toSortableId } from '../legend-sortable/sortable-ids'
import { styles } from './styles'

export interface LegendGroupProps {
  groupId: string
  /** `<Legend.Actions>` in the sticky header; member `<Legend.Row>`s in the body. */
  children?: ReactNode
}

/**
 * Store-connected group wrapper. Draggable inside `<Legend.Sortable>`.
 *
 * @experimental This API is new and may change in a future release.
 */
export function LegendGroup({ groupId, children }: LegendGroupProps) {
  const id = useLegendId()
  const group = useLegendShallow(id, (s) => s.groups[groupId])
  const setGroupCollapsed = useLegendShallow(id, (s) => s.setGroupCollapsed)
  const hidden = useLegendStore(
    id,
    (s) => selectGroupVisibility(s, groupId) === 'hidden',
  )
  const sortable = useLegendSortable()
  // Member ids only — useShallow ignores opacity/visibility noise on siblings.
  const memberSortableIds = useLegendShallow(id, (s) =>
    selectLayersByGroup(s, groupId).map((l) => toSortableId('layer', l.id)),
  )

  if (!group) return null

  const { actions, body } = partitionLegendChildren(children)
  const toggle = () => setGroupCollapsed(groupId, !group.collapsed)

  const renderGroup = (sortableProps?: SortableEntityRenderProps) => (
    <LegendGroupContext.Provider value={groupId}>
      <Box
        ref={sortableProps?.rootRef}
        style={sortableProps?.rootStyle}
        sx={[
          styles.group,
          sortableProps?.dragging === true && styles.groupDragging,
        ]}
      >
        <Box sx={styles.header}>
          {sortableProps?.handle}
          {/* Whole title area toggles collapse (accordion header); the
              actions box is a sibling outside the click target. */}
          <Box
            sx={styles.titleArea}
            role='button'
            tabIndex={0}
            aria-expanded={!group.collapsed}
            onClick={toggle}
            onKeyDown={accordionKeyDown(toggle)}
          >
            {group.icon != null && (
              <Box sx={styles.groupIcon}>{group.icon}</Box>
            )}

            <SmartTooltip title={group.label} dependencies={[group.label]}>
              {({ ref }) => (
                <Typography
                  ref={ref}
                  variant='button'
                  fontWeight='bold'
                  color={hidden ? 'text.disabled' : 'text.primary'}
                  sx={styles.label}
                >
                  {group.label}
                </Typography>
              )}
            </SmartTooltip>

            {/* Informative only (the row is the button); hidden on touch. */}
            <ExpandMoreIcon
              sx={[styles.chevron, group.collapsed && styles.chevronCollapsed]}
            />
          </Box>

          <Box className='PsLegend-groupActions' sx={styles.actions}>
            {actions}
          </Box>
        </Box>

        <Collapse in={!group.collapsed}>
          {sortable ? (
            <SortableContext
              items={memberSortableIds}
              strategy={verticalListSortingStrategy}
            >
              {body}
            </SortableContext>
          ) : (
            body
          )}
        </Collapse>
      </Box>
    </LegendGroupContext.Provider>
  )

  return sortable ? (
    <SortableEntity kind='group' id={groupId} render={renderGroup} />
  ) : (
    renderGroup()
  )
}
