import { IconButton } from '@mui/material'
import { CheckBoxOutlined } from '@mui/icons-material'
import { useCallback, useEffect } from 'react'
import type { LockSelectionProps, LockSelectionState } from './types'
import { actionButtonStyles } from '../shared/styles'
import { Tooltip } from '../../../components'
import { widgetStoreActions } from '../../stores/widget-store'
import { useWidgetSelector } from '../../stores/use-widget-selector'
import type { EchartWidgetData } from '../../echart/types'

export const LOCK_SELECTION_TOOL_ID = 'lock-selection'

/**
 * Widget action button to lock the current selection.
 *
 * When locked, the widget data is filtered to only show the selected items.
 * The button is only visible when there are selected items.
 * Registers a transformation tool in the widget pipeline when mounted.
 *
 * @example
 * ```tsx
 * <LockSelection
 *   id="my-widget"
 *   order={30}
 *   selectedItems={selectedItems}
 * />
 * ```
 */
export function LockSelection({
  id,
  selectedItems,
  order = 30,
  labels,
  Icon,
  IconButtonProps,
}: LockSelectionProps) {
  const { storeIsLocked } = useWidgetSelector(id, (w) => ({
    storeIsLocked: (w as LockSelectionState | undefined)?.isLocked,
  }))

  const isLocked = storeIsLocked ?? false

  // Register tool once — fn reads lockedItems from the store at execution time
  useEffect(() => {
    widgetStoreActions.registerTool(id, {
      id: LOCK_SELECTION_TOOL_ID,
      order,
      enabled: false,
      fn: (data) => {
        const widget = widgetStoreActions.getWidget<LockSelectionState>(id)
        const items = widget?.lockedItems ?? []
        if (items.length === 0) return data

        return filterDataByLockedItems(data as EchartWidgetData, items)
      },
    })

    return () => widgetStoreActions.unregisterTool(id, LOCK_SELECTION_TOOL_ID)
  }, [id, order])

  // Sync enabled from store — lightweight, no re-registration.
  // When selectedItems is empty (e.g., remount with no active selection),
  // disable the tool and clear stale lock state.
  useEffect(() => {
    if (isLocked && selectedItems.length === 0) {
      widgetStoreActions.setWidget(id, { isLocked: false, lockedItems: [] })
      return
    }
    widgetStoreActions.setToolEnabled(id, LOCK_SELECTION_TOOL_ID, isLocked)
  }, [id, isLocked, selectedItems.length])

  const handleToggle = useCallback(() => {
    if (isLocked) {
      // Unlock: clear locked items and disable tool
      widgetStoreActions.setWidget(id, {
        isLocked: false,
        lockedItems: [],
      })
    } else {
      // Lock: save selected items and enable tool
      widgetStoreActions.setWidget(id, {
        isLocked: true,
        lockedItems: selectedItems,
      })
    }
  }, [id, isLocked, selectedItems])

  // Don't render if no selections
  if (selectedItems.length === 0) {
    return null
  }

  const tooltipLabel = isLocked
    ? (labels?.unlock ?? 'Unlock selection')
    : (labels?.lock ?? 'Lock selection')

  const ariaLabel = labels?.ariaLabel ?? tooltipLabel

  return (
    <Tooltip title={tooltipLabel}>
      <IconButton
        size='small'
        aria-label={ariaLabel}
        onClick={handleToggle}
        sx={actionButtonStyles.trigger}
        data-active={isLocked}
        {...IconButtonProps}
      >
        {Icon ?? <CheckBoxOutlined fontSize='small' />}
      </IconButton>
    </Tooltip>
  )
}

/**
 * Filters widget data to only include items with names matching the locked items.
 */
function filterDataByLockedItems(
  data: EchartWidgetData,
  lockedItems: string[],
): EchartWidgetData {
  return data.map((series) =>
    series.filter((item) => {
      const name = item.name
      return typeof name === 'string' && lockedItems.includes(name)
    }),
  )
}
