import { useWidgetId, useWidgetShallow } from '../stores'
import { RangeUI } from './range-ui'
import type { RangeItemValue, RangeWidgetData } from './types'

interface RangeSlice {
  data: RangeWidgetData
  formatter?: (value: number) => string
}

const rangeSelector = (s: {
  data: unknown
  formatter?: (value: number) => string
}): RangeSlice => ({
  data: (s.data ?? []) as RangeWidgetData,
  formatter: s.formatter,
})

export interface RangeProps {
  /**
   * Fires on every pointer tick while a thumb is being dragged. Use this
   * for cheap UI updates (local state, optimistic display).
   */
  onChange?: (index: number, value: RangeItemValue) => void
  /**
   * Fires once when the user *releases* a slider thumb (or when the text
   * inputs blur / Enter, or when an arrow-key adjustment settles). Use
   * this for expensive side-effects you want throttled to drag end —
   * e.g. writing the value to a source filter that refetches widgets.
   */
  onChangeCommitted?: (index: number, value: RangeItemValue) => void
}

/**
 * Stateful Range bridge — reads `data` (post-pipeline) and `formatter` from
 * the per-widget store and forwards them to the pure {@link RangeUI}. Per
 * the destination-owned principle, value changes flow back through
 * `onChange` (per-tick) and `onChangeCommitted` (drag end) — the consumer
 * is expected to update the data prop on `<Provider>`. Use `disabled` on
 * individual `RangeDataItem`s to disable specific rows.
 */
export function Range({ onChange, onChangeCommitted }: RangeProps) {
  const id = useWidgetId()
  const slice = useWidgetShallow(id, rangeSelector)
  return (
    <RangeUI
      items={slice.data}
      formatter={slice.formatter}
      onChange={onChange}
      onChangeCommitted={onChangeCommitted}
    />
  )
}
