import { GridCellEditStopReasons, GridRenderCellParams, useGridApiContext } from "@mui/x-data-grid"
import React, { memo, useMemo, useRef, useState } from "react"
import { TreeCellNode } from "./types"
import { removeUndefine } from "../../../utils"
import { Box, Popper } from "@mui/material"
import { SimpleTreeView, TreeItem2 } from "@mui/x-tree-view"
import RefreshIcon from "../../../ui-utils/RefreshIcon"
import ClearIcon from "@mui/icons-material/Clear"
import { CustomIcon } from "../../../ui-utils"

const buildIndex = (nodes: TreeCellNode[], dict?: Record<string, TreeCellNode>) => {
  const d = dict || {}
  nodes.forEach(n => {
    d[n.nodeId] = n
    n.children && buildIndex(n.children, d)
  })
  return d
}

function filterTreeNodes(treeNodes: TreeCellNode[], filterString?: string): TreeCellNode[] {
  if (!filterString) return treeNodes

  const filterTreeNode = (treeNode: TreeCellNode) => {
    if (treeNode.title.indexOf(filterString) !== -1) return treeNode
    if (!treeNode.children || treeNode.children.length === 0) return undefined
    const children = filterTreeNodes(treeNode.children, filterString)
    if (children && children.length > 0) {
      return { ...treeNode, children }
    }
    return undefined
  }
  return treeNodes.map(filterTreeNode).filter(removeUndefine)
}

const rendTreeCellNode = (node: TreeCellNode) => {
  const childrenNodes = node.children ? rendTreeCellNodes(node.children) : null
  return (
    <TreeItem2 key={node.nodeId} itemId={node.nodeId} label={node.title}>
      {childrenNodes}
    </TreeItem2>
  )
}

const rendTreeCellNodes = (nodes: TreeCellNode[]) => {
  return nodes.map(rendTreeCellNode)
}

export const TreeSelectCell = memo(
  ({
    cellParams,
    rootNodes,
    isLoading,
    refreshHandler,
    enableClear,
  }: {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    cellParams: GridRenderCellParams<any, Record<string, unknown>[]>
    rootNodes: TreeCellNode[]
    isLoading?: boolean
    refreshHandler?: () => void
    enableClear?: boolean
  }) => {
    const { id, field } = cellParams
    const nodeIndex = React.useMemo(() => buildIndex(rootNodes), [rootNodes])
    const divRef = useRef<HTMLDivElement>(null)
    const apiRef = useGridApiContext()
    const [showPops, setShowPops] = useState(false)

    const [filterString, setFilterString] = useState("")
    const filteredTreeNodes = useMemo(() => filterTreeNodes(rootNodes, filterString), [rootNodes, filterString])
    const onNodeSelect = (_event: React.SyntheticEvent, nodeId: string) => {
      const node = nodeIndex[nodeId]
      if (node.canBeChoosed) {
        apiRef.current.setEditCellValue({ id, field, value: node.value === undefined ? node.nodeId : node.value })

        if (!node.disableAutoSelect) {
          setShowPops(false)
          apiRef.current.publishEvent("cellEditStop", {
            ...cellParams,
            reason: GridCellEditStopReasons.cellFocusOut,
          })
        }
      }
    }
    const onClear = () => {
      apiRef.current.setEditCellValue({ id, field, value: "" })
      setShowPops(false)
      apiRef.current.publishEvent("cellEditStop", {
        ...cellParams,
        reason: GridCellEditStopReasons.cellFocusOut,
      })
    }
    React.useEffect(() => {
      setShowPops(true)
    }, [])

    const refreshButton =
      isLoading !== undefined && refreshHandler !== undefined ? (
        <RefreshIcon isLoading={isLoading} handler={refreshHandler} />
      ) : null

    const clearButton = enableClear ? <CustomIcon icon={<ClearIcon />} handler={onClear} /> : null

    return (
      <div>
        <div ref={divRef}>
          <span>请选择</span>
          {refreshButton}
          {clearButton}
        </div>
        <Popper open={showPops} anchorEl={divRef.current} sx={{ zIndex: 2000 }}>
          <Box
            sx={{
              minHeight: 180,
              flexGrow: 1,
              maxWidth: 300,
              maxHeight: 450,
              overflow: "auto",
              bgcolor: "background.paper",
            }}
          >
            <div>
              过滤:<input type="text" value={filterString} onChange={e => setFilterString(e.target.value)}></input>
            </div>
            <SimpleTreeView onItemClick={onNodeSelect}>{rendTreeCellNodes(filteredTreeNodes)}</SimpleTreeView>
          </Box>
        </Popper>
      </div>
    )
  },
)


