import { IconButton } from '@mui/material'
import { useCallback, useEffect, useMemo } from 'react'
import { widgetStoreActions } from '../../stores/widget-store'
import type { StackToggleProps, StackToggleState } from './types'
import { actionButtonStyles } from '../shared/styles'
import { Tooltip } from '../../../components'
import { GroupedBarChartIcon } from './grouped-bar-chart-icon'
import { getEChartStackConfig } from '../../echart/utils'
import { DEFAULT_STACK_GROUP } from '../../echart/const'
import type { EchartWidgetState } from '../../echart/types'
import type { EchartOptionsProps } from '../../echart/types'
import { useWidgetSelector } from '../../stores/use-widget-selector'

export const STACK_TOGGLE_TOOL_ID = 'stack-toggle'

/**
 * Widget action to toggle stacking behavior in ECharts bar and histogram widgets.
 *
 * Registers as a config pipeline tool so that stack configuration is automatically
 * re-applied when the base config is updated (e.g., by WidgetLoader).
 *
 * @example
 * ```tsx
 * <StackToggle
 *   id="my-widget"
 *   defaultIsStacked={false}
 * />
 * ```
 */
export function StackToggle({
  id,
  defaultIsStacked = false,
  labels,
  Icon,
  IconButtonProps,
}: StackToggleProps) {
  const { storeIsStacked, option } = useWidgetSelector(id, (w) => ({
    storeIsStacked: (w as StackToggleState | undefined)?.isStacked,
    option: (w as EchartWidgetState | undefined)?.option,
  }))

  const { hasMultiSeries, hasStackInSeries } = useMemo(() => {
    if (!option) return { hasMultiSeries: false, hasStackInSeries: false }
    const series = Array.isArray(option.series)
      ? option.series
      : [option.series]
    return {
      hasMultiSeries: series.length > 1,
      hasStackInSeries: series.some((s) => (s as { stack?: string })?.stack),
    }
  }, [option])

  // If series already has stack defined, default to stacked=true
  const effectiveDefaultIsStacked = hasStackInSeries || defaultIsStacked
  const isStacked = storeIsStacked ?? effectiveDefaultIsStacked

  // Register config tool once — fn has no closure deps
  useEffect(() => {
    widgetStoreActions.registerTool(id, {
      id: STACK_TOGGLE_TOOL_ID,
      type: 'config',
      order: 10,
      enabled: false,
      fn: (currentConfig: unknown) => {
        const config = currentConfig as Record<string, unknown>
        const option = config.option as EchartOptionsProps | undefined
        if (!option) return currentConfig

        const series = Array.isArray(option.series)
          ? option.series
          : [option.series]
        const updatedSeries = series.map((s) => {
          const existingStack = (s as { stack?: string })?.stack
          const stackGroup =
            typeof existingStack === 'string'
              ? existingStack
              : DEFAULT_STACK_GROUP
          return { ...s, ...getEChartStackConfig(stackGroup) }
        })

        return { ...config, option: { ...option, series: updatedSeries } }
      },
    })
    return () => widgetStoreActions.unregisterTool(id, STACK_TOGGLE_TOOL_ID)
  }, [id])

  // Sync enabled from store — lightweight, no re-registration
  useEffect(() => {
    widgetStoreActions.setToolEnabled(
      id,
      STACK_TOGGLE_TOOL_ID,
      isStacked && hasMultiSeries,
    )
  }, [id, isStacked, hasMultiSeries])

  // Initialize store with default value only if not already configured
  useEffect(() => {
    if (storeIsStacked !== undefined) return
    widgetStoreActions.setWidget(id, { isStacked: effectiveDefaultIsStacked })
  }, [effectiveDefaultIsStacked, id, storeIsStacked])

  const handleToggle = useCallback(() => {
    widgetStoreActions.setWidget(id, { isStacked: !isStacked })
  }, [isStacked, id])

  const tooltipLabel = isStacked
    ? (labels?.unstacked ?? 'Disable stacking')
    : (labels?.stacked ?? 'Enable stacking')

  // Early return if there's only one series - stacking doesn't apply
  if (!hasMultiSeries) {
    return null
  }

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