/* eslint-disable @typescript-eslint/no-explicit-any */
import { klona } from "klona"
import { set } from "lodash-es"
import { DEFAULT_BODY_COLUMNS_NUMBER } from "@/page/App/components/dotPanel/constant/canvas"
import { searchDSLByDisplayName } from "@/redux/currentApp/components/componentsSelector"
import { componentsActions } from "@/redux/currentApp/components/componentsSlice"
import { getExecution } from "@/redux/currentApp/executionTree/executionSelector"
import { FocusManager } from "@/utils/focusManager"
import { DisplayNameGenerator } from "@/utils/generators/generateDisplayName"
// import { getActionMixedList } from "../redux/currentApp/action/actionSelector"
import { copyWidgetDisplayNameHelper } from "./changeDisplayNameHelper"
// import { buildTreeByMapNode } from "./componentNode/flatTree"
import { ComponentMapNode, ComponentTreeNode } from "@/redux/currentApp/components/componentsState"
import { buildTreeByMapNode } from "./componentNode/flatTree"

const doPaste = (
  originCopyComponents: ComponentTreeNode[],
 
  sources: "keyboard" | "duplicate",
  store: any
) => {

  store.dispatch(componentsActions.addComponentReducer(originCopyComponents))
}

export class CopyManager {
  static currentCopyComponentNodes: ComponentMapNode[] | null = null
  static copiedColumnNumber: number = DEFAULT_BODY_COLUMNS_NUMBER

  // static currentCopyAction: ActionItem<ActionContent> | null = null

  // static copyActionByActionID(actionID: string) {
  //   // const actionList = getActionMixedList(store.getState())
  //   const targetAction = actionList.find((item) => {
  //     return item.actionID === actionID
  //   })
  //   if (targetAction) {
  //     this.currentCopyAction = targetAction
  //   } else {
  //     this.currentCopyAction = null
  //   }
  // } 

  static copyComponentNodeByDisplayName(displayNames: string[], store) {
    if (displayNames.length > 0) {
      this.currentCopyComponentNodes = displayNames.map((displayName) => {
        return searchDSLByDisplayName(displayName, store.getState())
      })
     
    }
  }

  static paste(sources: "keyboard" | "duplicate", store: any) {
    // IMPAKTAPPSSnapshot.setSnapshot(widgetLayoutInfos)
    switch (FocusManager.getFocus()) {
      // case "data_action":
      // case "action":
      //   if (this.currentCopyAction != null) {
      //     onCopyActionItem(this.currentCopyAction)
      //   }
      //   break
      case "data_component":
      case "canvas":
        if (this.currentCopyComponentNodes != null) {
          const clickPosition = FocusManager.getClickPosition()
          const needCopyModalComponents = this.currentCopyComponentNodes
            .filter((item) => item.type === "MODAL_WIDGET")
            .map((needCopyComponent) => {
              const targetNodeParentNode = searchDSLByDisplayName(
                needCopyComponent.parentNode!,
                store
              )

              return this.copyComponent(
                buildTreeByMapNode(needCopyComponent.displayName, store),
                targetNodeParentNode.displayName,
                needCopyComponent.x,
                needCopyComponent.y,
                store
              )
            })
          const needCopyOtherComponents = this.currentCopyComponentNodes
            .filter((item) => item.type !== "MODAL_WIDGET")
          const copyResult = [...needCopyModalComponents]
          if (clickPosition) {
            switch (clickPosition.type) {
              case "component":
                // eslint-disable-next-line no-case-declarations
                const targetNode = searchDSLByDisplayName(
                  clickPosition.displayName,
                  store
                )
                if (targetNode && targetNode.parentNode) {
                
                  switch (targetNode.type) {
                    case "FORM_WIDGET":
                    case "MODAL_WIDGET": {
                      const targetParentNode = searchDSLByDisplayName(
                        targetNode.childrenNode[1], store.getState()
                      )
                      if (targetParentNode) {
                        let prevY = 0
                        copyResult.push(
                          ...needCopyOtherComponents.map((node) => {
                            const newNode = this.copyComponent(
                              buildTreeByMapNode(node.displayName, store),
                              targetParentNode.displayName,
                              0,
                              prevY,
                              store
                            )
                            prevY += node.h
                            return newNode
                          }),
                        )
                      }
                      break
                    }
                    case "CONTAINER_WIDGET": {
                      const executionTree = getExecution(
                        store.getState(),
                      ).result
                      const { currentIndex } =
                        executionTree[targetNode.displayName]
                      const targetParentNode = searchDSLByDisplayName(
                        targetNode.childrenNode[currentIndex], store.getState()
                      )
                      if (targetParentNode) {
                        let prevY = 0
                        copyResult.push(
                          ...needCopyOtherComponents.map((node) => {
                            const newNode = this.copyComponent(
                              buildTreeByMapNode(node.displayName, store),
                              targetParentNode.displayName,
                              0,
                              prevY,
                              store
                            )
                            prevY += node.h
                            return newNode
                          }),
                        )
                      }
                      break
                    }
                    case "LIST_WIDGET":
                    case "GRID_LIST_WIDGET": {
                      const targetParentNode = searchDSLByDisplayName(
                        targetNode.childrenNode[0],
                        store
                      )
                      if (targetParentNode) {
                        let prevY = 0
                        copyResult.push(
                          ...needCopyOtherComponents.map((node) => {
                            const newNode = this.copyComponent(
                              buildTreeByMapNode(node.displayName, store),
                              targetParentNode.displayName,
                              0,
                              prevY,
                              store
                            )
                            prevY += node.h
                            return newNode
                          }),
                        )
                      }
                      break
                    }
                    default: {
                      const targetParentNode = searchDSLByDisplayName(
                        targetNode.parentNode,
                        store.getState()
                      )
                      if (targetParentNode) {
                        let leftTopX = Number.MAX_SAFE_INTEGER
                        let leftTopY = Number.MAX_SAFE_INTEGER
                        needCopyOtherComponents.forEach((node) => {
                          leftTopX = Math.min(leftTopX, node.x)
                          leftTopY = Math.min(leftTopY, node.y)
                        })
                        copyResult.push(
                          ...needCopyOtherComponents.map((node) => {
                            return this.copyComponent(
                              buildTreeByMapNode(node.displayName, store),
                              targetParentNode.displayName,
                              targetNode!.x + node.x - leftTopX,
                              targetNode!.y + targetNode!.h + node.y - leftTopY,
                              store
                            )
                          }),
                        )
                      }
                    }
                  }
                  doPaste(
                    copyResult,
                    sources,
                    store.getState()
                  )
                } else {
                  // message.normal({
                  //   content: i18n.t("frame.paste_no_aimed"),
                  // })
                }
                break
              case "inner_container":
                if (clickPosition.clickPosition.length !== 2) {
                  // message.normal({
                  //   content: i18n.t("frame.paste_no_aimed"),
                  // })
                  return
                }
                // eslint-disable-next-line no-case-declarations
                const containerNode = searchDSLByDisplayName(
                  clickPosition.displayName, store.getState()
                )
                if (containerNode) {
                
                  let leftTopX = Number.MAX_SAFE_INTEGER
                  let leftTopY = Number.MAX_SAFE_INTEGER

                  this.currentCopyComponentNodes.forEach((node) => {
                    leftTopX = Math.min(leftTopX, node.x)
                    leftTopY = Math.min(leftTopY, node.y)
                  })

                  const originCopyComponents =
                    this.currentCopyComponentNodes.map((node) => {
                  
                      const needCopyComponent = node;
                      if (needCopyComponent.type === "MODAL_WIDGET") {
                        const targetNodeParentNode = searchDSLByDisplayName(
                          needCopyComponent.parentNode!, store.getState()
                        )
                        return this.copyComponent(
                          buildTreeByMapNode(needCopyComponent.displayName, store),
                          targetNodeParentNode.displayName,
                          needCopyComponent.x,
                          needCopyComponent.y,
                          store,
                          // copyComponent,

                        )
                      }
                      return this.copyComponent(
                        buildTreeByMapNode(needCopyComponent.displayName, store),
                        containerNode.displayName,
                        clickPosition.clickPosition[0] +
                        needCopyComponent.x -
                        leftTopX,
                        clickPosition.clickPosition[1] +
                        needCopyComponent.y -
                        leftTopY,
                        store
                      )
                    })

                  doPaste(
                    originCopyComponents,
                    sources,
                    store.getState()
                  )
                } else {
                  // message.normal({
                  //   content: i18n.t("frame.paste_no_aimed"),
                  // })
                }
                break
              case "group":
                // eslint-disable-next-line no-case-declarations
                const targetParentNode = searchDSLByDisplayName(
                  clickPosition.displayName, store.getState()
                )
                if (targetParentNode) {
               
                  let leftTopX = Number.MAX_SAFE_INTEGER
                  let leftTopY = Number.MAX_SAFE_INTEGER
                  this.currentCopyComponentNodes.forEach((node) => {
                    leftTopX = Math.min(leftTopX, node.x)
                    leftTopY = Math.min(leftTopY, node.y)
                  })

                  const originCopyComponents =
                    this.currentCopyComponentNodes.map((node) => {
                      const needCopyComponent = node;
                      if (needCopyComponent.type === "MODAL_WIDGET") {
                        const targetNodeParentNode = searchDSLByDisplayName(
                          needCopyComponent.parentNode!, store.getState()
                        )
                        return this.copyComponent(
                          buildTreeByMapNode(needCopyComponent.displayName, store),
                          targetNodeParentNode.displayName,
                          needCopyComponent.x,
                          needCopyComponent.y,
                          store
                        )
                      }
                      return this.copyComponent(
                        buildTreeByMapNode(needCopyComponent.displayName, store),
                        targetParentNode.displayName,
                        clickPosition.clickPosition[0] +
                        needCopyComponent.x -
                        leftTopX,
                        clickPosition.clickPosition[1] +
                        clickPosition.clickPosition[3] +
                        needCopyComponent.y -
                        leftTopY,
                        store
                      )
                    })

                  doPaste(
                    originCopyComponents,
                    sources, store.getState()
                  )
                }
            }
          }
        }
        break
      case "none":
        break
      case "components_config":
        break
      case "page_config":
        break
      case "data_page":
        break
      case "data_global_state":
        break
      case "widget_picker":
        break
    }
  }

  static copyComponent(
    node: ComponentTreeNode,
    newParentNodeDisplayName: string,
    rawX: number,
    rawY: number,
    store: any
  ): ComponentTreeNode {
    const newDisplayName = DisplayNameGenerator.generateDisplayName(
      node.type,
      node.showName,
    )

    const updatePathsMapValue = copyWidgetDisplayNameHelper(
      node.displayName,
      newDisplayName, store.getState()
    )

    const newNode = klona({
      ...node,
      props: node.props ?? {},
      displayName: newDisplayName,
      x: rawX,
      y: rawY,
      w: node.w,
      h: node.h,
      parentNode: newParentNodeDisplayName,
    } as ComponentTreeNode)

    Object.keys(updatePathsMapValue).forEach((key) => {
      set(newNode, `props.${key}`, updatePathsMapValue[key])
    })

    if (Array.isArray(node.childrenNode)) {
      newNode.childrenNode = node.childrenNode.map((n) =>
        this.copyComponent(n, newNode.displayName, n.x, n.y, store),
      )
    }
    return newNode
  }
}


