import {memo, useCallback, useMemo, useRef, useState} from 'react';
import {styled} from "styled-components";
import {ActionIcon} from "../../ActionIcon.jsx";
import {Popconfirm} from "antd";
import {RelationForm} from "../../../pages/ModalManage/components/RelationForm.jsx";
import {addEdge, MarkerType, useReactFlow} from "@xyflow/react";
import {getChildrenByParentId, splitParentAndChild} from "../utils.js";
import {useAppDispatch, useAppSelector} from "../../../../redux/configureStore";
import {selectTableList} from "../../../pages/MainPage/slice/selectors";
import {getTableList} from "../../../pages/MainPage/slice/thunks";
import {useWorkFlow} from "../../../hooks/useWorkFlow";
import {ACTION_TYPES, CARD_TYPE} from "../constants";

const commonWidth = 500;
const headHeight = 38;

export const CardNode = memo(({
  id,
  data,
  positionAbsoluteX,
  positionAbsoluteY
}) => {
  const dispatch = useAppDispatch();
  const targetTable = useAppSelector(selectTableList);
  const {getNodes} = useReactFlow();
  const {updateNodesState, updateEdgesState,getNodesState,getEdgesState} = useWorkFlow();
  const [open, setOpen] = useState(false);

  /** 新增关联对话框 */
  const formRef = useRef();

  /** 关联对话框数据 */
  const popRef = useRef({
    type: '新增表关联',
    enumType: {},
  });

  /** 新增表节点并插入内容 */
  const handleFinish = useCallback((values) => {
    const {sourceId, db ,condition} = data;
    if (CARD_TYPE.TABLE===condition){
      const {sourceFields, targetTable, targetFields,queryFields} = values;
      // 插入所有Field节点
      const fieldInfo = queryFields.map((v, index) => {
        const obj = JSON.parse(v)
        return {
          id: `${targetTable}.${obj.columnName}`,
          type: 'fields',
          position: {x: 0, y: index * 40},
          data: {
            sourceId,
            db,
            label: obj.columnName,
            description: obj.comment,
            type: obj.dataType,
            isKey: obj.columnName === 'id'
          },
          draggable: false,
          parentId: targetTable,
          extent: 'parent',
        }
      })

      // 插入Table节点
      const tableInfo = {
        id: targetTable,
        type: 'table',
        data: {
          condition:CARD_TYPE.TABLE,
          sourceId,
          db,
          height: fieldInfo.length * 40,
          label: targetTable,
        },
        position: {x: positionAbsoluteX + commonWidth + 50, y: positionAbsoluteY},
      }

      // 插入连接线
      const edgeInfo = {
        style: {strokeWidth: 2, stroke: 'black'},
        type: 'smoothstep',
        markerEnd: {
          type: MarkerType.ArrowClosed,
          color: 'black',
        },
        source: sourceFields,
        target: `${targetTable}.${targetFields}`
      }

      updateNodesState([
        ...getNodesState,
        tableInfo,
        ...fieldInfo,
      ])

      updateEdgesState(
        addEdge(edgeInfo, getEdgesState)
      )
      setOpen(false)
    }
  },[getNodesState,getEdgesState]);

  /** 删除表及子节点 */
  const deleteTable = useCallback(() => {

    updateNodesState(
      getNodesState.filter(item => !(item.id === id || item.parentId === id))
    )

    // 删除有效的子节点相关的连接
    updateEdgesState(
      getEdgesState.filter(item =>
        !getNodesState
          .filter(item => item.id === id || item.parentId === id)
          .some(del =>
            item.target === del.id || item.source === del.id
          )
      )
    )
  },[getNodesState,getEdgesState])

  //CardNode抬头里的操作器
  const handleAction = (action) => {
    const {key} = action;
    if (key !== 'remove') {
      const {db, sourceId, label} = data;
      const {children} = splitParentAndChild(getNodes());
      const sourceFields = getChildrenByParentId(children, id, true);
      const sourceTable = {label, value: id}
      dispatch(getTableList(data))
      popRef.current = {
        title: key === "add" ? '新增表关联' : '更改关联关系',
        enumType: {
          db,
          sourceId,
          sourceFields,
          targetTable,
          sourceTable
        }
      }
      setOpen(true)
    } else {
      deleteTable()
    }
  }

  const popPanel = useMemo(() => {
    return (
      <Popconfirm
        open={open}
        icon={false}
        placement="bottomLeft"
        title={popRef.current.title}
        description={<RelationForm ref={formRef} submitter={false} options={popRef.current.enumType} onFinish={handleFinish}/>}
        onConfirm={() => formRef.current?.submit()}
        onCancel={() => setOpen(false)}
        arrow={false}
      />
    )
  }, [open]);

  return (
    <>
      {popPanel}
      <CustomNode style={{height: data.height}}>
        <CustomHead>
          <Wrapper>
            <Title>
              {data?.label}
            </Title>
            <Extra>
              <ActionIcon items={ACTION_TYPES[data.condition]} onSelect={handleAction}/>
            </Extra>
          </Wrapper>
        </CustomHead>
      </CustomNode>
    </>
  )
})

const CustomHead = styled.div`
  position: absolute;
  width: ${commonWidth-25}px;;
  top: ${-headHeight}px;
  z-index: 1001;
  display: flex;
  justify-content: center;
  flex-direction: column;
  min-height: ${headHeight}px;
  margin-bottom: -1px;
  padding: 0 12px;
  color: ${p => p.theme.colorTextBase};
  font-weight: 600;
  font-size: 14px;
  background: transparent;
`

const Wrapper = styled.div`
  width: ${commonWidth-25}px;
  display: flex;
  align-items: center;
  box-sizing: border-box;
`

const Title = styled.div`
  display: inline-block;
  flex: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  box-sizing: border-box;
  text-align: center;
`

const Extra = styled.div`
  margin-inline-start: auto;
  color: ${p => p.theme.colorTextBase};
  font-weight: normal;
  font-size: 14px;
  box-sizing: border-box;
`

const CustomNode = styled.div`
  width: ${commonWidth}px;
  min-height: 40px;
  border-radius: 0 0 6px 6px;
  background: ${p => p.theme.colorBgContainer};

  &:before {
    content: '';
    position: absolute;
    top: ${-headHeight}px;
    left: 50%;
    height: ${headHeight}px;
    width: ${commonWidth}px;
    transform: translate(-50%, 0);
    background: linear-gradient(322.88deg, rgba(51, 112, 255, .15) 0%, rgba(51, 169, 255, .15) 99.46%);
    z-index: 1000;
    line-height: 1;
    border-radius: 6px 6px 0 0;
  }

  &:after {
    content: '';
    position: absolute;
    top: -38px;
    left: 50%;
    height: ${headHeight}px;
    width: ${commonWidth}px;
    transform: translate(-50%, 0);
    background: ${p => p.theme.colorBgContainer};
    border-radius: 6px 6px 0 0;
  }
`