import { useCallback, type ComponentType } from 'react'
import { IconButton, type SvgIconProps } from '@mui/material'
import { Search as SearchIcon } from '@mui/icons-material'
import { Tooltip } from '../../../components'
import {
  getWidgetStore,
  useSingleTransform,
  useWidget,
  useWidgetId,
} from '../../stores'
import { filterBySearchText } from './filter'
import { DEFAULT_SEARCHER_LABELS, type SearcherLabels } from './labels'
import { styles } from './style'

const SEARCHER_DESCRIPTOR = {
  id: 'searcher',
  type: 'data' as const,
  order: 20,
  disables: ['lock-selection'],
}

export interface SearcherToggleProps {
  labels?: Partial<SearcherLabels>
  icon?: ComponentType<SvgIconProps>
  iconProps?: SvgIconProps
  /**
   * Whether the searcher transform is enabled on first mount. Defaults
   * to `false` so the toggle renders un-pressed and the
   * `filterBySearchText` transform stays dormant until the user clicks
   * it. Set to `true` for search-first widgets where the input is the
   * primary affordance.
   */
  initialEnabled?: boolean
}

export function SearcherToggle({
  labels,
  icon: Icon = SearchIcon,
  iconProps,
  initialEnabled = false,
}: SearcherToggleProps) {
  const id = useWidgetId()
  const resolved = { ...DEFAULT_SEARCHER_LABELS, ...labels }
  const text = useWidget(
    id,
    (s) => (s.transformStates.searcher?.searchText as string | undefined) ?? '',
  )

  // The transform fn closes over `text`. Memoize via useCallback so identity
  // only changes when text changes, allowing useTransform to re-register.
  const fn = useCallback(
    (data: unknown) => filterBySearchText(data, text),
    [text],
  )

  const { enabled, toggle } = useSingleTransform(id, SEARCHER_DESCRIPTOR, fn, {
    initialEnabled,
  })

  return (
    <Tooltip title={resolved.toggle}>
      <IconButton
        size='small'
        aria-label={resolved.toggle}
        aria-pressed={enabled}
        onClick={toggle}
        sx={{ ...styles.toggle, ...(enabled && styles.toggleActive) }}
      >
        <Icon fontSize='small' {...iconProps} />
      </IconButton>
    </Tooltip>
  )
}

/**
 * Imperatively writes the search text into the widget store. Used by the
 * Searcher input to update text inside transformStates without going through
 * a re-rendered React subscription.
 */
export function setSearcherText(widgetId: string, value: string): void {
  getWidgetStore(widgetId).setState((s) => ({
    transformStates: {
      ...s.transformStates,
      searcher: {
        enabled: s.transformStates.searcher?.enabled ?? false,
        ...s.transformStates.searcher,
        searchText: value,
      },
    },
  }))
}
