"use client"

import {
  ActionIcon,
  Box,
  Collapse,
  Flex,
  Group,
  Paper,
  ScrollArea,
  Stack,
  Switch,
  Text,
  Title,
  Tooltip,
} from "@mantine/core"
import { ChevronDown, ChevronUp, Link2Off, Pencil, Trash2 } from "lucide-react"
import { useCallback, useState } from "react"
import { Project } from "../api/project/typing"
import { LabelState } from "../LabelNossr"
import { useKeyEventStore, useLabelStore, useObjectStore } from "../store"
import { useBottomToolsStore } from "../useBottomToolsStore"
import { useOtherToolsStore } from "../useOtherToolsStore"
import { getShowContextMenuPosition, usePaperStore } from "../usePaperStore"
import { renderGroupPath } from "../useRenderGroupPath"
import { useRightToolsStore } from "../useRightToolsStore"
import { useTopToolsStore } from "../useTopToolsStore"
import { labelTypeMap } from "../utils/constants"
import RightGroupEditModal from "./RightGroupEditModal"

interface RightGroupToolsComponentProps {
  labelState: LabelState
  projectDetail?: Project.DetailResponse
}

const RightGroupTools: React.FC<RightGroupToolsComponentProps> = (props) => {
  const { projectDetail } = props

  const [open, setOpen] = useState(false)
  const [editId, setEditId] = useState<number | null>(null)
  const getOperationSchema = useCallback(
    (operationId: string) => {
      return (
        projectDetail?.label_schema_list?.find(
          (item) => item.category_id === +operationId
        ) || null
      )
    },
    [projectDetail?.label_schema_list]
  )
  const { setLabel, pushStateStack } = useLabelStore()
  const { pathGroupMap, groupPathVisible, setGroupPathVisible } =
    useRightToolsStore()
  const { activeImage } = useBottomToolsStore()
  const { groupStatus, updateGroupStatus, selectedPath, updateSelectedPath } =
    useObjectStore()
  const { getItemById, getItemsById } = usePaperStore()
  const { shift: pressShift } = useKeyEventStore()
  const [isGroupCollapsed, setIsGroupCollapsed] = useState<boolean>(true)

  const handleSelect = useCallback(
    (id: number) => {
      let operationId = getItemById(id)?.data.operationId
      if (selectedPath[activeImage]?.length) {
        if (!selectedPath[activeImage]?.includes(id)) {
          if (pressShift) {
            if (getItemsById(id)?.length) {
              getItemsById(id).forEach((item) => {
                item.fillColor = item.data?.fillColor
              })
              let category = useTopToolsStore
                .getState()
                .objectOperations.find(
                  (item) => item.category_id.toString() === operationId
                )
              const globalPosition = getItemById(id)!.globalMatrix.transform(
                getItemById(id)!.position
              )
              const { top, left } = getShowContextMenuPosition(
                globalPosition,
                category!
              )
              useOtherToolsStore.getState().setShowContextMenu({
                showContextMenu: true,
                position: { top, left },
                imageId: activeImage,
                operationId: operationId,
                id,
              })
            }
          } else {
            selectedPath[activeImage].forEach((selectedId) => {
              if (getItemsById(selectedId)?.length) {
                getItemsById(selectedId).forEach((item) => {
                  item.fillColor = item.data?.blankColor
                })
                useOtherToolsStore.getState().setShowContextMenu({
                  showContextMenu: false,
                  position: {
                    top: 0,
                    left: 0,
                  },
                  imageId: activeImage,
                  operationId: operationId,
                  id,
                })
              }
            })
            if (getItemsById(id)?.length) {
              getItemsById(id).forEach((item) => {
                item.fillColor = item.data?.fillColor
              })
              let category = useTopToolsStore
                .getState()
                .objectOperations.find(
                  (item) => item.category_id.toString() === operationId
                )
              const globalPosition = getItemById(id)!.globalMatrix.transform(
                getItemById(id)!.position
              )
              const { top, left } = getShowContextMenuPosition(
                globalPosition,
                category!
              )
              useOtherToolsStore.getState().setShowContextMenu({
                showContextMenu: true,
                position: { top, left },
                imageId: activeImage,
                operationId: operationId,
                id,
              })
            }
          }
          updateSelectedPath(activeImage, "ADD", id)
        } else {
          updateSelectedPath(activeImage, "DELETE", id)
          if (getItemsById(id)?.length) {
            getItemsById(id).forEach((item) => {
              item.fillColor = item.data?.blankColor
            })
            useOtherToolsStore.getState().setShowContextMenu({
              showContextMenu: false,
              position: {
                top: 0,
                left: 0,
              },
              imageId: activeImage,
              operationId: operationId,
              id,
            })
          }
        }
      } else {
        updateSelectedPath(activeImage, "ADD", id)
        if (getItemsById(id)?.length) {
          getItemsById(id).forEach((item) => {
            item.fillColor = item.data?.fillColor
          })
          let category = useTopToolsStore
            .getState()
            .objectOperations.find(
              (item) => item.category_id.toString() === operationId
            )
          const globalPosition = getItemById(id)!.globalMatrix.transform(
            getItemById(id)!.position
          )
          const { top, left } = getShowContextMenuPosition(
            globalPosition,
            category!
          )
          useOtherToolsStore.getState().setShowContextMenu({
            showContextMenu: true,
            position: { top, left },
            imageId: activeImage,
            operationId: operationId,
            id,
          })
        }
      }
    },
    [
      activeImage,
      getItemById,
      getItemsById,
      pressShift,
      selectedPath,
      updateSelectedPath,
    ]
  )

  const getOperationIdByPathId = (pathId: number) => {
    let pathItem = getItemById(pathId)
    return pathItem?.data?.operationId || ""
  }

  const unlinkGroup = (id: number) => {
    const group = usePaperStore.getState().group
    const imageId = useBottomToolsStore.getState().activeImage
    const groupMap =
      useRightToolsStore.getState().pathGroupMap.get(imageId) ??
      new Map<number, number[]>()

    if (!group) return
    if (!Array.from(groupMap.values()).length) return
    // update children path data
    const currentGroupChildrenIds = groupMap.get(id) ?? []
    const needUpdateOperationIds: any[] = []
    currentGroupChildrenIds?.forEach((childId, index) => {
      const childPath = usePaperStore.getState().getItemById(childId)!
      childPath.data.parentGroupId = null
      if (childPath.data.operationId && !needUpdateOperationIds[index])
        needUpdateOperationIds[index] = childPath.data.operationId
    })
    // handle labeldata update
    const currentData = structuredClone(useLabelStore.getState().label)
    needUpdateOperationIds.forEach((operationId, index) => {
      if (currentData.get(imageId)?.get(operationId)?.length) {
        let result =
          currentData
            .get(imageId)
            ?.get(operationId)
            ?.map((item) =>
              item[0] !== currentGroupChildrenIds[index]
                ? item
                : [
                    item[0],
                    item[1],
                    { ...item[2], parentGroupId: null },
                    item[3],
                  ]
            ) || []
        currentData.get(imageId)?.set(operationId, result as any)
      }
    })
    // update group tool
    useRightToolsStore.getState().removePathGroupInMap(imageId, id)
    // setlabeldata
    setLabel(currentData)
    pushStateStack(currentData)
  }

  const deleteGroup = (id: number) => {
    const group = usePaperStore.getState().group
    const imageId = useBottomToolsStore.getState().activeImage
    const groupMap =
      useRightToolsStore.getState().pathGroupMap.get(imageId) ??
      new Map<number, number[]>()

    if (!group) return
    if (!Array.from(groupMap.values()).length) return

    // remove group children
    const currentGroupChildrenIds = groupMap.get(id) ?? []
    const needRemoveOperationIds: any[] = []
    currentGroupChildrenIds?.forEach((childId, index) => {
      const childPaths = group.getItems({ data: { id: childId } })
      childPaths.forEach((p) => {
        p.remove()
        if (p.data.operationId && !needRemoveOperationIds[index])
          needRemoveOperationIds[index] = p.data.operationId
      })
    })
    const currentData = structuredClone(useLabelStore.getState().label)
    needRemoveOperationIds.forEach((operationId, index) => {
      if (currentData.get(imageId)?.get(operationId)?.length) {
        let result =
          currentData
            .get(imageId)
            ?.get(operationId)
            ?.filter((item) => item[0] !== currentGroupChildrenIds[index]) || []
        currentData.get(imageId)?.set(operationId, result)
      }
    })
    // update group tool
    useRightToolsStore.getState().removePathGroupInMap(imageId, id)
    setLabel(currentData)
    pushStateStack(currentData)
  }

  return (
    <Box h="100%" w="100%">
      <Flex direction="column" h="100%" gap="xs">
        <Flex justify="space-between" align="center" px="md" py="xs">
          <Title order={4} size="h4">
            群组列表
          </Title>
          <ActionIcon
            variant="subtle"
            onClick={() => setIsGroupCollapsed(!isGroupCollapsed)}>
            {isGroupCollapsed ? (
              <ChevronUp size={16} />
            ) : (
              <ChevronDown size={16} />
            )}
          </ActionIcon>
        </Flex>
        <Collapse
          in={isGroupCollapsed}
          style={{
            flex: 1,
            display: "flex",
            flexDirection: "column",
            overflow: "hidden",
          }}>
          <Flex direction="column" h="100%">
            <Box px="md" py="xs">
              <Group gap="xs">
                <Text size="sm">展示群组框</Text>
                <Switch
                  onLabel="是"
                  offLabel="否"
                  checked={groupPathVisible}
                  onChange={(event) => {
                    setGroupPathVisible(event.currentTarget.checked)
                    renderGroupPath()
                  }}
                />
              </Group>
            </Box>
            <ScrollArea style={{ flex: 1 }} px="md">
              <Stack gap="xs" pb="md">
                {pathGroupMap.get(activeImage) &&
                  Array.from(pathGroupMap.get(activeImage)!.keys())?.map(
                    (groupId) => {
                      const isOpen =
                        !groupStatus[activeImage + groupId]?.["COLLAPSE"]
                      return (
                        <Box key={groupId} w="100%">
                          <Paper withBorder p="xs" radius="md" shadow="sm">
                            <Flex justify="space-between" align="center">
                              <Group>
                                <Text size="sm" ff="mono">
                                  @{groupId}
                                </Text>
                                <Group
                                  gap={4}
                                  display={
                                    useTopToolsStore.getState().isView
                                      ? "none"
                                      : "flex"
                                  }>
                                  <Tooltip label="编辑群组">
                                    <ActionIcon
                                      variant="subtle"
                                      size="sm"
                                      onClick={() => {
                                        setOpen(true)
                                        setEditId(groupId)
                                      }}>
                                      <Pencil size={14} />
                                    </ActionIcon>
                                  </Tooltip>
                                  <Tooltip label="解除群组">
                                    <ActionIcon
                                      variant="subtle"
                                      size="sm"
                                      onClick={() => {
                                        unlinkGroup(groupId)
                                      }}>
                                      <Link2Off size={14} />
                                    </ActionIcon>
                                  </Tooltip>
                                  <Tooltip label="删除群组">
                                    <ActionIcon
                                      variant="subtle"
                                      color="red"
                                      size="sm"
                                      onClick={() => {
                                        deleteGroup(groupId)
                                      }}>
                                      <Trash2 size={14} />
                                    </ActionIcon>
                                  </Tooltip>
                                </Group>
                              </Group>
                              <Group gap="xs">
                                <Text size="sm">
                                  {pathGroupMap.get(activeImage)?.get(groupId)
                                    ?.length || 0}
                                </Text>
                                <ActionIcon
                                  variant="subtle"
                                  size="sm"
                                  onClick={() => {
                                    updateGroupStatus(
                                      activeImage + groupId,
                                      "COLLAPSE",
                                      isOpen
                                    )
                                  }}>
                                  {isOpen ? (
                                    <ChevronUp size={14} />
                                  ) : (
                                    <ChevronDown size={14} />
                                  )}
                                </ActionIcon>
                              </Group>
                            </Flex>
                          </Paper>
                          <Collapse in={isOpen}>
                            <Stack gap="xs" mt="xs" pl="xs">
                              {pathGroupMap
                                .get(activeImage)
                                ?.get(groupId)
                                ?.map((child) => {
                                  const isSelected =
                                    selectedPath[activeImage]?.includes(child)
                                  return (
                                    <Paper
                                      withBorder
                                      p="xs"
                                      radius="md"
                                      shadow="sm"
                                      key={child}
                                      bg={
                                        isSelected
                                          ? "var(--mantine-primary-color-filled)"
                                          : undefined
                                      }
                                      c={isSelected ? "white" : undefined}
                                      onClick={() => {
                                        handleSelect(child)
                                      }}
                                      style={{ cursor: "pointer" }}>
                                      <Flex
                                        justify="flex-end"
                                        align="center"
                                        gap="md">
                                        <Text size="sm">
                                          {child}-
                                          {labelTypeMap.get(
                                            getOperationSchema(
                                              getOperationIdByPathId(child)
                                            )?.label_type || 0
                                          )}
                                        </Text>
                                      </Flex>
                                    </Paper>
                                  )
                                })}
                            </Stack>
                          </Collapse>
                        </Box>
                      )
                    }
                  )}
              </Stack>
            </ScrollArea>
          </Flex>
        </Collapse>
      </Flex>
      {open && (
        <RightGroupEditModal
          open={open}
          editId={editId}
          afterChange={(val: number) => {
            setEditId(val)
          }}
          closeModal={() => {
            setOpen(false)
            setEditId(null)
          }}
        />
      )}
    </Box>
  )
}

export default RightGroupTools
