import { Box, IconButton } from '@mui/material'
import { HighlightAltOutlined } from '@mui/icons-material'
import { useCallback, useEffect, useRef } from 'react'
import { widgetStoreActions } from '../../stores/widget-store'
import type { BrushSelectedItems, BrushState, BrushToggleProps } from './types'
import { styles } from './style'
import { Tooltip } from '../../../components'
import { useWidgetSelector } from '../../stores/use-widget-selector'
import { BrushOverlay } from './brush-overlay'

/**
 * Kept for backwards compatibility. The tool is no longer registered with the
 * widget store — brush state is now owned directly by this component and the
 * associated DOM overlay instead of being driven through the config pipeline.
 * Existing code that looks this constant up in `registeredTools` will simply
 * find no match.
 */
export const BRUSH_TOGGLE_TOOL_ID = 'brush-toggle'

/**
 * Widget action to toggle brush-style selection on bar and histogram widgets.
 *
 * Renders a toggle button and a portaled overlay rendered inside the chart's
 * `<div>`. The overlay handles all pointer interactions, draws selection
 * rectangles in DOM, and hit-tests against the widget data. All state lives
 * in the widget store — rectangles survive config-pipeline re-renders
 * (`setOption({ notMerge: true })`) automatically.
 *
 * Only intended for bar and histogram widgets (both use `xAxis.type === 'category'`).
 *
 * @example
 * ```tsx
 * <BrushToggle
 *   id="my-widget"
 *   onBrushSelected={(items) => console.log(items)}
 * />
 * ```
 */
export function BrushToggle({
  id,
  onBrushSelected,
  multiBrush,
  selections,
  defaultEnabled = false,
  labels,
  Icon,
  IconButtonProps,
}: BrushToggleProps) {
  // Single subscription for everything this component cares about.
  const { brush, selection } = useWidgetSelector(id, (w) => {
    const s = w as BrushState | undefined
    return {
      brush: s?.brush ?? defaultEnabled,
      selection: s?.brushSelection,
    }
  })

  // Seed the widget store with `defaultEnabled` on first mount. Guarded so
  // remounts don't stomp whatever the user has toggled to.
  useEffect(() => {
    const current = widgetStoreActions.getWidget<BrushState>(id)?.brush
    if (current === undefined) {
      widgetStoreActions.setWidget(id, { brush: defaultEnabled })
    }
  }, [id, defaultEnabled])

  const handleToggle = useCallback(() => {
    if (brush) {
      // Disabling: keep rectangles visible so the consumer's selection stays
      // in sync. Re-enabling clears them below (fresh slate each activation).
      widgetStoreActions.setWidget(id, { brush: false })
    } else {
      widgetStoreActions.setWidget(id, {
        brush: true,
        brushRects: [],
        brushSelection: { dataIndex: [], seriesIndex: 0 },
      })
      // Mirror the clear to the consumer so its selection drops with the
      // visual rectangles.
      onBrushSelected?.({ dataIndex: [], seriesIndex: 0 })
    }
  }, [brush, id, onBrushSelected])

  // Invoke the consumer's callback whenever the overlay writes a new
  // selection to the store. `selection` is a new object reference on each
  // pointerup so a simple reference check is enough.
  const lastSelectionRef = useRef<BrushSelectedItems | undefined>(undefined)
  useEffect(() => {
    if (!selection) return
    if (lastSelectionRef.current === selection) return
    lastSelectionRef.current = selection
    onBrushSelected?.(selection)
  }, [selection, onBrushSelected])

  // Consumer-driven clear: when `selections` transitions to 0 (e.g. the user
  // presses the clear button in `WidgetSelectionSummary`), drop all drawn
  // rectangles and any stored selection.
  useEffect(() => {
    if (selections !== 0) return
    const state = widgetStoreActions.getWidget<BrushState>(id)
    const hasRects = (state?.brushRects?.length ?? 0) > 0
    const hasSelection = (state?.brushSelection?.dataIndex?.length ?? 0) > 0
    if (!hasRects && !hasSelection) return
    widgetStoreActions.setWidget(id, {
      brushRects: [],
      brushSelection: { dataIndex: [], seriesIndex: 0 },
    })
  }, [selections, id])

  const enableLabel = labels?.enable ?? 'Enable brush selection'
  const disableLabel = labels?.disable ?? 'Disable brush selection'
  const tooltipLabel = brush ? disableLabel : enableLabel

  return (
    <>
      <Box sx={styles.container}>
        <Tooltip title={tooltipLabel}>
          <IconButton
            size='small'
            aria-label={labels?.ariaLabel ?? tooltipLabel}
            onClick={handleToggle}
            sx={styles.trigger}
            data-active={brush}
            {...IconButtonProps}
          >
            {Icon ?? <HighlightAltOutlined />}
          </IconButton>
        </Tooltip>
      </Box>
      <BrushOverlay id={id} multiBrush={multiBrush} />
    </>
  )
}
