import { useMemo } from 'react'
import { useDominoStore, useDominoStoreInstance } from './domino-hooks'
import { useDominoScrollIntoView } from './use-domino-scroll-into-view'
import { useDominoZoomToFit } from './use-domino-zoom-to-fit'
import type { Viewport, SceneElement } from './domino'

/**
 * The Facade hook for Domino Canvas.
 * Provides a unified object to control the canvas, inspired by useReactFlow.
 */
export function useDominoInstance(
  explicitContainerRef?: React.RefObject<HTMLElement | null>,
) {
  const store = useDominoStoreInstance()
  const setViewport = useDominoStore(state => state.setViewport)
  const addElement = useDominoStore(state => state.addElement)
  const removeElement = useDominoStore(state => state.removeElement)
  const updateElement = useDominoStore(state => state.updateElement)
  const undo = useDominoStore(state => state.undo)
  const redo = useDominoStore(state => state.redo)
  const takeSnapshot = useDominoStore(state => state.takeSnapshot)
  const moveElementUp = useDominoStore(state => state.moveElementUp)
  const moveElementDown = useDominoStore(state => state.moveElementDown)
  const moveElementToTop = useDominoStore(state => state.moveElementToTop)
  const moveElementToBottom = useDominoStore(state => state.moveElementToBottom)

  const scrollIntoView = useDominoScrollIntoView(explicitContainerRef)
  const zoomToFit = useDominoZoomToFit(explicitContainerRef)

  const instance = useMemo(
    () => ({
      /**
       * Get current viewport state (raw access)
       */
      getViewport: () => store.getState().viewport,
      /**
       * Set viewport state explicitly
       */
      setViewport: (viewport: Partial<Viewport>) => setViewport(viewport),
      /**
       * Zoom the canvas to fit all elements
       */
      zoomToFit,
      /**
       * Scroll a specific element into view
       */
      scrollIntoView,
      /**
       * Manual zoom by multiplier at center
       */
      zoomBy: (multiplier: number, cx: number, cy: number) => {
        store.getState().zoomViewport(multiplier, cx, cy)
      },
      /**
       * Undo the last change
       */
      undo,
      /**
       * Redo the last undone change
       */
      redo,
      /**
       * Manually take a history snapshot
       */
      takeSnapshot,
      /**
       * Add a new element to the canvas
       */
      addElement: (el: SceneElement) => addElement(el),
      /**
       * Remove an element by ID
       */
      removeElement: (id: string) => removeElement(id),
      /**
       * Update an element's data
       */
      updateElement: (id: string, updates: Partial<SceneElement>) =>
        updateElement(id, updates),
      /**
       * Move an element up in the rendering order
       */
      moveElementUp: (id: string) => moveElementUp(id),
      /**
       * Move an element down in the rendering order
       */
      moveElementDown: (id: string) => moveElementDown(id),
      /**
       * Move an element to the very top
       */
      moveElementToTop: (id: string) => moveElementToTop(id),
      /**
       * Move an element to the very bottom
       */
      moveElementToBottom: (id: string) => moveElementToBottom(id),
    }),
    [
      store,
      setViewport,
      zoomToFit,
      scrollIntoView,
      undo,
      redo,
      takeSnapshot,
      addElement,
      removeElement,
      updateElement,
      moveElementUp,
      moveElementDown,
      moveElementToTop,
      moveElementToBottom,
    ],
  )

  return instance
}
