import {
  createContext,
  useContext,
  useState,
  type PropsWithChildren,
} from 'react'
import { useStore } from 'zustand'
import { createLassoToolsStore } from './store'
import type { StoreApi } from 'zustand'
import type { LassoToolsProviderProps, LassoToolsStore } from './types'

const LassoToolsContext = createContext<StoreApi<LassoToolsStore>>(
  {} as StoreApi<LassoToolsStore>,
)

/**
 * React context provider that manages lasso tools state and configuration across multiple map instances.
 *
 * @remarks
 * Typically used at the application level to provide consistent lasso tool state
 * across multiple map components. Works in conjunction with `LassoTools` and `LassoTools.Controls`.
 *
 * @example
 * ```tsx
 * <LassoToolsProvider values={[{
 *   mapId: 'main-map',
 *   enabled: false,
 *   modeSelected: 'polygon',
 *   modes: DEFAULT_LASSO_TOOLS_MODES,
 *   modeInstance: new DEFAULT_LASSO_TOOLS_MODES.polygon.mode(),
 * }]}>
 *   <MapComponent id="main-map" />
 *   <LassoTools mapId="main-map">...</LassoTools>
 * </LassoToolsProvider>
 * ```
 */
export function LassoToolsProvider({
  children,
  values,
}: PropsWithChildren<LassoToolsProviderProps>) {
  const [storeRef] = useState(() => createLassoToolsStore(values))

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

/**
 * Hook to access lasso tools state from the nearest `LassoToolsProvider` 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 `LassoToolsProvider`.
 */
export function useLassoToolsState<T>(
  selector: (state: LassoToolsStore) => T,
): T {
  const store = useContext(LassoToolsContext)
  if (!Object.keys(store).length) {
    throw new Error('Missing LassoToolsProvider in the tree')
  }
  return useStore(store, selector)
}
