import {memo, useCallback, useEffect, useMemo, useRef} from 'react';
import {ProForm, ProFormDatePicker, ProFormSelect, ProFormText} from "@ant-design/pro-components";
import {Col, Row} from "antd";
import {WorkFlowPanel} from "../../../components/WorkFlow";
import {styled} from "styled-components";
import {useAppDispatch, useAppSelector} from "../../../../redux/configureStore";
import {selectDBList, selectDBSource, selectTableColumns, selectTableList} from "../../MainPage/slice/selectors";
import {getDBList, getTableColumns, getTableList} from "../../MainPage/slice/thunks";
import {useWorkFlow} from "../../../hooks/useWorkFlow";
import {CARD_TYPE, WORKFLOW_DEFAULT_STYLE} from "../../../components/WorkFlow/constants";
import {MarkerType} from "@xyflow/react";
import useI18NPrefix from "../../../hooks/useI18NPrefix";
import {pinyin} from "pinyin-pro";

export const QuickStartStep = memo(({
  initialValues,
  onSetField
}) => {
  const t = useI18NPrefix('global');
  const { updateEdgesState,updateNodesState , getNodesState, getEdgesState } = useWorkFlow();
  const dispatch = useAppDispatch();
  const computeRef = useRef({
    db:null,
    sourceId:null,
    tableName:null,
  });
  const fieldWidth = 450;

  const initTableName = useMemo(()=>{
    const modelDetail = initialValues?.modelDetail;
    let tableName;
    if (modelDetail?.joinRelations?.length>0){
      tableName = modelDetail?.joinRelations[0]?.left
    }else {
      tableName = modelDetail?.fields[0]?.tableName
    }
    return tableName
  },[initialValues]);

  useEffect(() => {
    if (initialValues){
      const {datasourceId,dbName,modelDetail} = initialValues;
      getDBbySourceId(datasourceId)
      getTableByDBName(dbName)
      let tableName;
      if (modelDetail?.joinRelations?.length>0){
        tableName = modelDetail?.joinRelations[0]?.left
        handleValueChange(tableName)
        initFieldsNode(initialValues)
      }else {
        tableName = modelDetail?.fields[0]?.tableName
        handleValueChange(tableName)
        initSingleTable(initialValues)
      }
    }
  }, [initialValues]);
  /** 数据源 */
  const dbSource = useAppSelector(selectDBSource);
  /** 数据库 */
  const dbList = useAppSelector(selectDBList);
  /** 表 */
  const tableList = useAppSelector(selectTableList);
  /** 字段数据 */
  const fieldList = useAppSelector(selectTableColumns);
  /** 根据数据源ID获取数据库 */
  const getDBbySourceId = useCallback((sourceId)=>{
    if (sourceId){
      computeRef.current.sourceId=sourceId;
      dispatch(getDBList({sourceId}))
    }
  },[getNodesState])

  /** 根据数据源ID获取数据库 */
  const getTableByDBName = useCallback((db)=>{
    if (db){
      computeRef.current.db=db
      const {sourceId} = computeRef.current;
      dispatch(getTableList({sourceId,db}))
    }
  },[])

  /** 根据数据源ID获取数据库 */
  const handleValueChange = useCallback((tableName)=>{
    computeRef.current.tableName=tableName
    const {sourceId,db} = computeRef.current;
    dispatch(getTableColumns({sourceId,db,tableName}))
    const table = {
      id: tableName,
      type: 'table',
      data:{
        condition:CARD_TYPE.TABLE,
        db,
        sourceId,
        label: tableName,
        height:40
        //description: tableName,
      },
      position: { x: 50, y: 50 }
    };
    updateNodesState([table])
  },[])

  /** 单表查询的模型回显 */
  const initSingleTable = useCallback((init)=>{
    const {sourceId,db} = computeRef.current;
    const {fields} = init.modelDetail;
    const tableNode = {
      id: fields[0]?.tableName,
      type: 'table',
      data:{
        condition:CARD_TYPE.TABLE,
        db,
        sourceId,
        label: fields[0]?.tableName,
        height:(fields.length)*40
      },
      position: { x: 50, y: 50 }
    }
    const initialNodes = [
      tableNode,
      ...fields.map((item,index)=>({
        id: `${item.tableName}.${item.fieldName}`,
        type: 'fields',
        position: { x: 0, y: index*40 },
        data:{
          db,
          sourceId,
          label:item.fieldName,
          description: item.comment,
          type:item.dataType,
          isKey:item.fieldName.toLowerCase()==='id'
        },
        draggable:false,
        parentId: item.tableName,
        extent: 'parent',
      }))
    ]
    updateNodesState(initialNodes);
  },[])

  /** 字段初始化，插入设计器 */
  const initFieldsNode = useCallback((init)=>{
    const {sourceId,db} = computeRef.current;
    const {fields,joinRelations} = init.modelDetail;
    let relations = [];
    let initialNodes = [];
    let initialEdges = [];
    // 通过关系,插入关系表
    joinRelations.forEach(({
      left,
      right,
      leftFields,
      rightFields
    })=>{
      const leftField = leftFields[0];
      const rightField = rightFields[0];
      // 表节点 和 关系
      const isExist = relations.findIndex(item=> item.tableName===left )
      if (isExist<0){
        relations.push({tableName:left, fieldName:leftField})
      }
      relations.push({tableName:right, fieldName:rightField})

      // 节点关系Edges
      initialEdges.push({
        id:`xy-edge__${left}.${leftField}-${right}.${rightField}`,
        style: {strokeWidth: 2, stroke: 'black'},
        type: 'smoothstep',
        markerEnd: {
          type: MarkerType.ArrowClosed,
          color: 'black',
        },
        source: `${left}.${leftField}`,
        target: `${right}.${rightField}`
      })
    })

    // 插入字段
    relations.forEach((relation,index)=>{
      const tableFields = fields.filter(node=>node.tableName===relation.tableName)
      tableFields.forEach(
        (item,index)=>initialNodes.push({
          id: `${item.tableName}.${item.fieldName}`,
          type: 'fields',
          position: { x: 0, y: index*40 },
          data:{
            db,
            sourceId,
            label:item.fieldName,
            description: item.comment,
            type:item.dataType,
            isKey:item.fieldName.toLowerCase()==='id'
          },
          draggable:false,
          parentId: item.tableName,
          extent: 'parent',
        })
      )
      initialNodes.unshift({
        id: relation.tableName,
        type: 'table',
        data:{
          db,
          sourceId,
          label: relation.tableName,
          height:(tableFields.length)*40,
          condition:CARD_TYPE.TABLE,
        },
        position: { x: 50+600*index, y: 50 }
      })
    })
    updateNodesState(initialNodes);
    updateEdgesState(initialEdges);
  },[])

  /** 字段选择，插入设计器*/
  const onFieldSelect=useCallback((event,items)=>{
    // 表单数据
    const {sourceId,db,tableName} = computeRef.current;
    // 重新设置Table高度
    const tableNodes = getNodesState
      .filter(item=>item.type==="table")
      .map(table=> {
        if (table.id === tableName){
          return {
            ...table,
            data:{
              ...table.data,
              height: items.length*40
            }
          }
        }
        return table
      })
    // 本表的字段，勾选的
    const nodes = getNodesState.filter(node=>
      node.type!=="table" &&
      node.parentId===tableName
    );
    // 非本表的字段
    const outNodes = getNodesState.filter(item=>item.type!=="table" && item.parentId!==tableName);
    // 插入新增的
    const others = items.map((item,index)=>{
      const findItem = nodes.find(node=>node?.data?.label===item.columnName);
      if (findItem){
        // 重新计算位置
        return {
          ...findItem,
          position: { x: 0, y: index*40 },
        }
      }else {
        return {
          id: `${tableName}.${item.columnName}`,
          type: 'fields',
          position: { x: 0, y: index*40 },
          data:{
            db,
            sourceId,
            label:item.columnName,
            description: item.comment,
            type:item.dataType,
            isKey:item.columnName.toLowerCase()==='id'
          },
          draggable:false,
          parentId: tableName,
          extent: 'parent',
        }
      }
    })
    updateNodesState([...tableNodes,...others,...outNodes])
  },[getNodesState])

  const onNameChange = useCallback((e)=>{
    if (!initialValues){
      const py = pinyin(e.target.value, { toneType: "none", type: "array" });
      let pingYin = "";
      py.forEach(p=>pingYin+=p[0].toUpperCase());
      onSetField("bizName",pingYin)
    }
  },[])

  return (
    <div style={{height:850}}>
      <ProForm.Group>
        <ProFormSelect
          name="dbSource"
          label={t("formItem.datasource")}
          placeholder={t("placeholder.datasource")}
          width={fieldWidth}
          rules={[{ required: true }]}
          disabled={initialValues}
          initialValue={initialValues?.datasourceId}
          onChange={getDBbySourceId}
          options={dbSource}
        />
        <ProFormSelect
          name="db"
          showSearch
          width={fieldWidth}
          label={t("formItem.db")}
          placeholder={t("placeholder.db")}
          rules={[{ required: true }]}
          disabled={initialValues}
          initialValue={initialValues?.dbName}
          onChange={getTableByDBName}
          options={dbList}
        />
      </ProForm.Group>
      <ProForm.Group>
        <ProFormSelect
          name="tableName"
          label={t("formItem.table")}
          placeholder={t("placeholder.db")}
          showSearch
          width={fieldWidth}
          rules={[{ required: true }]}
          disabled={initialValues}
          initialValue={initTableName}
          onChange={handleValueChange}
          options={tableList}
        />
        <ProFormSelect
          name="fields"
          label={t("formItem.fields")}
          showSearch
          width={fieldWidth}
          options={fieldList}
          //disabled={initialValues}
          initialValue={
            (initialValues?.modelDetail?.fields||[])
              .filter(item=> item.tableName===initTableName)
              .map(item=>item.fieldName)
          }
          rules={[{ required: true }]}
          onChange={onFieldSelect}
          fieldProps={{
            mode: 'multiple',
            maxTagCount:'responsive',
          }}
        />
      </ProForm.Group>
      <ProForm.Group>
        <ProFormText
          name="name"
          label={t("formItem.model")+t("formItem.name")}
          placeholder={t("placeholder.modelName")}
          width={fieldWidth}
          rules={[{ required: true }]}
          onChange={onNameChange}
          initialValue={initialValues?.name}
        />
        <ProFormText
          name="bizName"
          label={t("formItem.bizName")}
          placeholder={t("placeholder.bizName")}
          width={fieldWidth}
          disabled={initialValues}
          rules={[{ required: true }]}
          initialValue={initialValues?.bizName}
        />
      </ProForm.Group>
      <ProForm.Group>
        <ProFormText
          name="description"
          label={t("formItem.model")+t("formItem.desc")}
          placeholder={t("placeholder.description")}
          width={fieldWidth}
          initialValue={initialValues?.description}
        />
        <ProFormDatePicker name="startDate" label={t("formItem.startDate")} width={fieldWidth} initialValue={initialValues?.startDate}/>
        {/*<ProFormDatePicker name="stopDate" label="失效日期" width={fieldWidth} initialValue={initialValues?.stopDate}/>*/}
      </ProForm.Group>
      <Row>
        <Col span={2}>
          <CardLabel children={t("title.relation")+":"}/>
        </Col>
        <Col span={22}>
          <WorkFlowPanel
            {...WORKFLOW_DEFAULT_STYLE}
            initialNodes={getNodesState}
            initialEdges={getEdgesState}
          />
        </Col>
      </Row>
    </div>
  )
})

const CardLabel = styled.label`
  margin-left: 30px;
  &.required {
    // 添加必填红色*的样式
    &::before {
      display: inline-block;
      margin-inline-end: 4px;
      color: #ff4d4f;
      font-size: 14px;
      font-family: SimSun, sans-serif;
      line-height: 1;
      content: "*";
    }
  }
`
