import {CopyFilled, DeleteFilled, EditFilled} from '@ant-design/icons'
import {type Edge, Handle, type Node, type NodeProps, NodeResizeControl, NodeToolbar, Position} from '@xyflow/react'
import {type ClassName, classnames, type Schema} from 'amis'
import {Button, Drawer, Space, Tooltip} from 'antd'
import {type CSSProperties, type JSX, useCallback, useState} from 'react'
import styled from 'styled-components'
import {amisRender, commonInfo, horizontalFormOptions} from '../../../util/amis.tsx'
import {generateAllIncomerOutputVariablesFormOptions} from '../Helper.tsx'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import {OutputVariableTypeMap} from '../types.ts'

export function inputsFormColumns(
  nodeId: string,
  inputSchema: Record<string, Record<string, any>>,
  nodes: Node[],
  edges: Edge[],
  data: any,
): Schema[] {
  return [
    {
      type: 'input-kvs',
      name: 'inputs',
      label: '输入变量',
      addButtonText: '新增输入',
      draggable: false,
      keyItem: {
        ...horizontalFormOptions(),
        label: '参数名称',
      },
      valueItems: [
        {
          ...horizontalFormOptions(),
          type: 'select',
          name: 'variable',
          label: '变量',
          required: true,
          selectMode: 'group',
          options: generateAllIncomerOutputVariablesFormOptions(
            nodeId,
            inputSchema,
            nodes,
            edges,
            data,
          ),
        },
      ],
    },
  ]
}

export function outputsFormColumns(editable: boolean = false, required: boolean = false): Schema[] {
  return [
    {
      disabled: !editable,
      type: 'input-kvs',
      name: 'outputs',
      label: '输出变量',
      addButtonText: '新增输出',
      draggable: false,
      keyItem: {
        ...horizontalFormOptions(),
        label: '参数名称',
      },
      required: required,
      valueItems: [
        {
          ...horizontalFormOptions(),
          type: 'select',
          name: 'type',
          label: '参数',
          required: true,
          selectFirst: true,
          options: Object.keys(OutputVariableTypeMap).map(key => ({
            // @ts-ignore
            label: OutputVariableTypeMap[key],
            value: key,
          })),
        },
      ],
    },
  ]
}

type AmisNodeProps = {
  className: ClassName,
  style?: CSSProperties,
  nodeProps: NodeProps
  extraNodeDescription?: JSX.Element
  handler: JSX.Element
  columnSchema?: () => Schema[]
  resize?: { minWidth: number, minHeight: number }
}

const AmisNodeContainerDiv = styled.div`
`

export const StartNodeHandler = () => {
  return <Handle type="source" position={Position.Right} id="source"/>
}

export const EndNodeHandler = () => {
  return <Handle type="target" position={Position.Left} id="target"/>
}

export const NormalNodeHandler = () => {
  return (
    <>
      <StartNodeHandler/>
      <EndNodeHandler/>
    </>
  )
}

export const nodeClassName = (name: string) => {
  return `flow-node flow-node-${name}`
}

const AmisNode: (props: AmisNodeProps) => JSX.Element = ({
  className,
  style,
  nodeProps,
  extraNodeDescription,
  handler,
  columnSchema,
  resize,
}) => {
  const {removeNode} = useFlowStore()
  const {getDataById, setDataById, removeDataById} = useDataStore()
  const {id} = nodeProps
  // @ts-ignore
  const nodeData = getDataById(id)
  const nodeName = nodeData?.node?.name ?? ''
  const nodeDescription = nodeData?.node?.description ?? ''

  const [editDrawerOpen, setEditDrawerOpen] = useState(false)
  const [editDrawerForm, setEditDrawerForm] = useState<JSX.Element>(<></>)
  const onOpenEditDrawerClick = useCallback(() => {
    setEditDrawerForm(
      amisRender(
        {
          type: 'wrapper',
          size: 'none',
          body: [
            {
              debug: commonInfo.debug,
              type: 'form',
              ...horizontalFormOptions(),
              wrapWithPanel: false,
              onEvent: {
                submitSucc: {
                  actions: [
                    {
                      actionType: 'custom',
                      // @ts-ignore
                      script: (context, action, event) => {
                        setDataById(
                          id,
                          {
                            ...context.props.data,
                            finished: true,
                          },
                        )
                        setEditDrawerOpen(false)
                      },
                    },
                  ],
                },
              },
              body: [
                {
                  type: 'input-text',
                  name: 'node.name',
                  label: '节点名称',
                  placeholder: nodeName,
                },
                {
                  type: 'textarea',
                  name: 'node.description',
                  label: '节点描述',
                  placeholder: nodeDescription,
                },
                {
                  type: 'divider',
                },
                ...(columnSchema?.() ?? []),
                {
                  type: 'wrapper',
                  size: 'none',
                  className: 'space-x-2 text-right',
                  body: [
                    {
                      type: 'action',
                      label: '取消',
                      onEvent: {
                        click: {
                          actions: [
                            {
                              actionType: 'custom',
                              // @ts-ignore
                              script: (context, action, event) => {
                                setEditDrawerOpen(false)
                              },
                            },
                          ],
                        },
                      },
                    },
                    {
                      type: 'submit',
                      label: '保存',
                      level: 'primary',
                    },
                  ],
                },
              ],
            },
          ],
        },
        getDataById(id),
      ),
    )
    setEditDrawerOpen(true)
  }, [id])
  const onRemoveClick = useCallback(() => {
    removeNode(id)
    removeDataById(id)
  }, [])
  return (
    <AmisNodeContainerDiv className={classnames(className, 'w-64')} style={style}>
      <Drawer
        title="节点编辑"
        open={editDrawerOpen}
        closeIcon={false}
        maskClosable={false}
        destroyOnHidden
        size="large"
      >
        {editDrawerForm}
      </Drawer>
      <NodeToolbar>
        <Space>
          <Tooltip title="复制节点">
            <Button
              className="text-secondary"
              disabled
              type="text"
              size="small"
              icon={<CopyFilled/>}
            />
          </Tooltip>
          <Tooltip title="编辑节点">
            <Button
              className="text-secondary"
              type="text"
              size="small"
              icon={<EditFilled/>}
              onClick={() => onOpenEditDrawerClick()}
            />
          </Tooltip>
          <Tooltip title="删除节点">
            <Button
              className="text-secondary"
              type="text"
              size="small"
              icon={<DeleteFilled/>}
              onClick={() => onRemoveClick()}
            />
          </Tooltip>
        </Space>
      </NodeToolbar>
      <div className="node-card h-full flex flex-col bg-white rounded-md border border-gray-100 border-solid">
        <div
          className="node-card-header items-center flex justify-between p-2 border-t-0 border-l-0 border-r-0 border-b border-gray-100 border-solid">
          <span className="font-bold">{nodeName}</span>
          <span className="text-gray-300 text-sm">{id}</span>
        </div>
        <div className="node-card-description flex flex-col flex-1 p-2 text-secondary text-sm">
          <div className="node-card-description-node">
            {nodeDescription}
          </div>
          <div className="node-card-description-extra flex-1 mt-1">
            {extraNodeDescription}
          </div>
        </div>
      </div>
      {resize ? <>
        <NodeResizeControl
          minWidth={resize.minWidth}
          minHeight={resize.minHeight}
        />
      </> : undefined}
      {handler}
    </AmisNodeContainerDiv>
  )
}

export default AmisNode
