import {
  createContext,
  useContext,
  useState,
  type PropsWithChildren,
} from 'react'
import { useStore } from 'zustand'
import { createMeasurementToolsStore } from './store'
import type { StoreApi } from 'zustand'
import type {
  MeasurementToolsProviderProps,
  MeasurementToolsStore,
} from './types'

const MeasurementToolsContext = createContext<StoreApi<MeasurementToolsStore>>(
  {} as StoreApi<MeasurementToolsStore>,
)

/**
 * React context provider that manages measurement tool state across multiple map instances.
 *
 * @remarks
 * Supports distance, area, and buffer measurements with multi-unit, localization, and
 * per-map configuration. Works with `MeasurementTools` and `MeasurementTools.Controls`.
 *
 * @example
 * ```tsx
 * <MeasurementToolsProvider values={[{
 *   mapId: 'main-map',
 *   modeSelected: 'distance',
 *   unit: 'kilometer',
 *   enabled: false,
 * }]}>
 *   <MeasurementTools mapId="main-map" />
 * </MeasurementToolsProvider>
 * ```
 */
export function MeasurementToolsProvider({
  children,
  values,
}: PropsWithChildren<MeasurementToolsProviderProps>) {
  const [storeRef] = useState(createMeasurementToolsStore(values))

  return (
    <MeasurementToolsContext.Provider value={storeRef}>
      {children}
    </MeasurementToolsContext.Provider>
  )
}

/**
 * Hook to access measurement tools state from the nearest `MeasurementToolsProvider` context.
 *
 * @param selector - Zustand selector function to pick specific state values.
 * @returns The selected state value.
 *
 * @remarks
 * Throws an error if used outside of a `MeasurementToolsProvider`.
 */
export function useMeasurementToolsState<T>(
  selector: (state: MeasurementToolsStore) => T,
): T {
  const store = useContext(MeasurementToolsContext)
  if (!Object.keys(store).length)
    throw new Error('Missing MeasurementToolsProvider in the tree')
  return useStore(store, selector)
}
