import React, { memo, useState, useCallback, useMemo } from 'react'
import type {
  ImageOCRResponse,
  RecognizedImageElement,
} from '../../service/type'
import { cn } from '@/utils/cn'
import {
  useDominoStoreInstance,
  useDominoInstance,
  useDominoElements,
  useDominoSelectedIds,
  useDominoElementUIStates,
  useDominoSelectionBounds,
  getDominoDOM,
  DominoCanvas,
  DominoAnchor,
  type ImageElement,
  type SceneElement,
  type TextElement,
} from '../canvas'

import { useDownLoadImageGroup } from '../../hooks/use-download-image-group'
import { useElementActions } from '../../hooks/use-element-actions'
import { useImageEditActions } from '../../hooks/use-image-edit-actions'
import { useLayout } from '../../hooks/use-layout'
import { useShortcuts } from '../../hooks/use-shortcuts'
import { usePasteHandler } from '../../hooks/use-paste-handler'
import { ArtboardActionsToolbar } from './artboard-actions-toolbar'
import ImageTextEditor from './image-text-editor'
import ImageRedrawEditor, { type RedrawState } from './image-redraw-editor'
import TopBar from './top-bar'
import BottomToolbar from './bottom-toolbar'
import SelectionOverlay from './selection-overlay'
import { ElementMetadata } from './element-metadata'
import { Loading } from './loading'

export interface DomiBoardProps {
  className?: string
  style?: React.CSSProperties
  /**
   * 列最大宽度
   */
  colMaxWidth?: number
  /**
   * 列间距
   */
  colGap?: number
  /**
   * 行间距
   */
  rowGap?: number
  /**
   * 返回文件列表回调，不传不显示返回按钮
   */
  onBack?: (e: React.MouseEvent) => void
  /**
   * 关闭图片编辑器回调，不传不显示关闭按钮
   */
  onClose?: () => void
  /**
   * 是否只读
   */
  readOnly?: boolean
  /**
   * 元素数据
   */
  elements?: Record<string, SceneElement>
  /**
   * 元素顺序
   */
  elementOrder?: string[]
  /**
   * 是否加载中
   */
  loading?: boolean
  /**
   * 任务ID/会话ID
   */
  taskId?: string
  /**
   * 是否展开
   */
  expand?: boolean
  /**
   * 切换展开状态回调
   */
  onToggleExpand?: (e: React.MouseEvent) => void
}

const DomiBoard = memo((props: DomiBoardProps) => {
  const {
    className,
    style,
    colMaxWidth = 7000,
    colGap = 40,
    rowGap = 120,
    onBack,
    onClose,
    readOnly = false,
    elements: externalElements,
    elementOrder: externalElementOrder,
    loading: externalLoading,
    expand,
    onToggleExpand,
  } = props

  const rootRef = React.useRef<HTMLDivElement>(null)

  // Semantic Read Hooks
  const elements = useDominoElements()
  const selectedIds = useDominoSelectedIds()
  const selectionBounds = useDominoSelectionBounds()
  const elementUIStates = useDominoElementUIStates()

  // Facade Instance Hook
  const instance = useDominoInstance()

  // Internal store access for low-level actions
  const store = useDominoStoreInstance()

  const [editingDimensionId, setEditingDimensionId] = useState<string | null>(
    null,
  )
  const [ocrData, setOcrData] = useState<ImageOCRResponse | null>(null)

  const selectedElements = useMemo(
    () => selectedIds.map(id => elements[id]).filter(Boolean),
    [selectedIds, elements],
  )
  const selectedElement = elements[selectedIds[0]] as ImageElement | undefined

  const { downloadImage, downloadCompositeImage } = useDownLoadImageGroup(
    selectionBounds,
    selectedElements,
  )

  const canvasInitViewport = useMemo(() => ({ scale: 0.25 }), [])
  const canvasPadding = useMemo(
    () => ({ top: 120, right: 20, bottom: 80, left: 120 }),
    [],
  )

  const layoutOptions = useMemo(
    () => ({
      colMaxWidth,
      colGap,
      rowGap,
      padding: canvasPadding,
    }),
    [colMaxWidth, colGap, rowGap, canvasPadding],
  )

  const { addElementToFlow } = useLayout(layoutOptions)

  const {
    handleAddArtboard,
    handleAddImage,
    handleAddImageFromFile,
    handleAddText,
    handleDeleteElements,
  } = useElementActions(
    props.taskId || '',
    addElementToFlow,
    instance.scrollIntoView,
  )

  const handleOnPartialRedraw = useCallback(
    (
      element: ImageElement,
      recognizedElements: readonly RecognizedImageElement[],
    ) => {
      store.getState().updateElementUIState(element.id, {
        redrawState: {
          marks: [],
          inputValue: '',
          recognizedElements: [...recognizedElements],
          docJson: undefined,
        },
      })
    },
    [store],
  )

  const {
    handleMatting,
    handlePartialRedraw,
    handleEditText,
    handleConfirmEditText,
    handleEditElements,
  } = useImageEditActions(
    props.taskId || '',
    addElementToFlow,
    handleOnPartialRedraw,
  )

  const handlePaste = usePasteHandler({
    readOnly,
    handleAddImageFromFile,
    handleAddText,
  })

  useShortcuts({
    rootRef,
    onDelete: handleDeleteElements,
    onPaste: handlePaste,
  })

  const renderElementMetadata = useCallback(
    ({ element }: { element: SceneElement }) => {
      return (
        <ElementMetadata
          element={element}
          onEditDimension={() => setEditingDimensionId(element.id)}
        />
      )
    },
    [setEditingDimensionId],
  )

  const handleSelect = useCallback(
    (ids: string[]) => {
      const {
        elements: currentElements,
        viewport,
        updateElement,
      } = store.getState()

      ids.forEach(id => {
        const el = currentElements[id]
        if (el && el.type === 'text' && (!el.width || !el.height)) {
          const domEl = getDominoDOM(id)
          if (domEl) {
            const rect = domEl.getBoundingClientRect()
            const scale = viewport.scale || 1
            const updates: Partial<TextElement> = {}

            if (!el.width) {
              updates.width = Math.ceil(rect.width / scale) + 1
              updates.originalWidth = updates.width
            }
            if (!el.height) {
              updates.height = Math.ceil(rect.height / scale)
              updates.originalHeight = updates.height
            }

            if (Object.keys(updates).length > 0) {
              updateElement(id, updates)
            }
          }
        }
      })
    },
    [store],
  )

  return (
    <div
      ref={rootRef}
      className={cn(
        'domi-board relative w-full h-full overflow-hidden bg-bg text-font font-sans',
        'group',
        className,
      )}
      tabIndex={-1}
      style={style}
    >
      {externalLoading ? (
        <Loading />
      ) : (
        <DominoCanvas
          initViewport={canvasInitViewport}
          minScale={0.02}
          maxScale={4}
          padding={canvasPadding}
          readOnly={readOnly}
          renderElementMetadata={renderElementMetadata}
          onSelect={handleSelect}
          elements={externalElements}
          elementOrder={externalElementOrder}
        >
          <SelectionOverlay
            elements={elements}
            selectedIds={selectedIds}
            selectionBounds={selectionBounds}
            toolbarVisible={
              selectedIds.length > 0 &&
              !ocrData &&
              !selectedIds.some(
                id =>
                  !!(elementUIStates[id]?.redrawState as
                    | RedrawState
                    | undefined),
              )
            }
            readOnly={readOnly}
            onMatting={handleMatting}
            onPartialRedraw={handlePartialRedraw}
            onEditText={(e: ImageElement) => handleEditText(e, setOcrData)}
            onEditElements={handleEditElements}
            downloadImage={downloadImage}
            downloadCompositeImage={downloadCompositeImage}
            moveElementUp={instance.moveElementUp}
            moveElementDown={instance.moveElementDown}
            moveElementToTop={instance.moveElementToTop}
            moveElementToBottom={instance.moveElementToBottom}
          />

          {(() => {
            if (!editingDimensionId) return null
            const element = elements[editingDimensionId]
            if (!element || element.type !== 'artboard') return null
            return (
              <ArtboardActionsToolbar
                element={element}
                onAction={actionId => {
                  if (actionId === 'download') {
                    downloadCompositeImage()
                  }
                  setEditingDimensionId(null)
                }}
              />
            )
          })()}

          <TopBar
            rootRef={rootRef}
            onBack={onBack}
            onClose={onClose}
            expand={expand}
            onToggleExpand={onToggleExpand}
          />

          {!readOnly && (
            <BottomToolbar
              onAddArtboard={handleAddArtboard}
              onAddImage={handleAddImage}
              onAddText={handleAddText}
            />
          )}
        </DominoCanvas>
      )}

      {ocrData && (
        <DominoAnchor
          id={selectedIds[0]}
          containerRef={rootRef}
          screenSpace
          placement='left-start'
        >
          {({ style: anchorStyle, measureRef }) => (
            <ImageTextEditor
              measureRef={measureRef}
              style={anchorStyle}
              ocrList={ocrData}
              onFinish={() => setOcrData(null)}
              onConfirm={updatedList => {
                handleConfirmEditText(
                  selectedElement as ImageElement,
                  updatedList,
                )
              }}
            />
          )}
        </DominoAnchor>
      )}

      {Object.entries(elements).map(([id, element]) => {
        const uiState = elementUIStates[id]
        const redrawState = uiState?.redrawState as RedrawState | undefined
        if (!redrawState || element.type !== 'image') return null

        return (
          <ImageRedrawEditor
            key={`redraw-${id}`}
            element={element as ImageElement}
            redrawState={redrawState}
            showToolbar={selectedIds[0] === id}
            addElementToFlow={addElementToFlow}
            containerRef={rootRef}
            taskId={props.taskId || ''}
            onFinish={() => {
              const { updateElementUIState } = store.getState()
              updateElementUIState(id, {
                status: 'idle',
                statusText: undefined,
                redrawState: undefined,
              })
            }}
          />
        )
      })}
    </div>
  )
})

export default memo(DomiBoard)
