import React, { useState, useEffect, useRef } from "react";
import { Tooltip, Modal, Pagination, Table, Typography } from 'antd';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import SmoothScroll from 'smooth-scroll';
import classnames from 'classnames';
import { Resizable } from 'react-resizable';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";
import ResizeObserver from 'rc-resize-observer';

import { dispatch } from '../../../../model'; 
import { showMessage, getQueryParam, paginate, isSzseEnv, formatDate } from '../../../../util';
import { AnchorId, AnchorTimestamp, Action, CatalogId, ModelerId } from '../../../../util/constant';
// import Tag from "../../Tag";

import './ModelTable.less';
import 'react-contexify/dist/ReactContexify.css';

const { Text } = Typography;

const ModelNameColumn = (props) => {
  const { text, record, detailItem } = props;
  const [ data, setData ] = useState(record);

  const cols = [
    {
      title: '序号',
      dataIndex: 'key',
      render: (text, record, index) => {
        return (index+1).toString();
      },
      width: 60,
      ellipsis: true,
    },
    {
      title: '字段中文名称',
      width: 160,
      dataIndex: 'cnName',
      editable: true,
      ellipsis: true,
    },
    {
      title: '字段英文名称',
      width: 160,
      dataIndex: 'name',
      editable: true,
      ellipsis: true,
    },
  ];

  let _textComponent = <span style={{ color: '#000' }}>{text}</span>;
  if (data.digest) {
    _textComponent = <div style={{ width: 500, maxHeight: 300, overflow: 'auto' }}>
      <Table 
        dataSource={data.digest.attributeDigests||[]}
        columns={cols}
        loading={false}
        pagination={false}
        size='small'
        rowClassName={(record, index) => {
          if (record?.primaryKey) {
            return 'primary-row';
          }

          return '';
        }}
      />
    </div>;
  }

  return (
    <Tooltip 
      title={_textComponent}
      overlayClassName='tooltip-common'
      onVisibleChange={(visible) => {
        if (visible && !record.digest) {
          dispatch({
            type: 'datamodel.getDataModelDigest',
            payload: {
              id: record.id
            },
            callback: _data => {
              record.digest = _data;
              setData({...record});
            }
          })
        }
      }}
    >
        <a onClick={()=>{detailItem(record);}}>
      {text||''}
      </a>
    </Tooltip>
  );
}

const ResizeableHeaderCell = props => {
  const { onResize, width, onClick, ...restProps } = props;

  if (!width) {
    return <th {...restProps} />;
  }

  return (
    <Resizable
      width={width}
      height={0}
      handle={
        <span
          className="react-resizable-handle"
          onClick={(e) => {
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{ enableUserSelectHack: false }}
    >
      <th
        onClick={onClick}
        {...restProps}
      />
    </Resizable>
  );
};

const ModelTable = (props) => {

  const { data, onChange, onItemAction, onSelect, onHistory, catalogId, keyword, onAutoCreateTable, offset = null, modelId = null, modelPid = null, view, selectModelerIds, onSubSelect, modelState } = props;

  const MENU_ID = (((modelId||'') !== '') ? `model-table-contextmenu-${modelId}` : 'model-table-contextmenu');

  const { show } = useContextMenu({
    id: MENU_ID,
  });
  
  const [ tableWidth, setTableWidth ] = useState(0);
  const [ selectedRowKeys, setSelectedRowKeys ] = useState([]);
  const [ subSelectedRowKeys, setSubSelectedRowKeys ] = useState([]);
  // const [ mouseEnterKey, setMouseEnterKey ] = useState(null);
  const [ sortRule, setSortRule ] = useState(null); 
  const [ filterData, setFilterData ] = useState([]);
  const [ subData, setSubData ] = useState([]);

  const cols = [
    {
      title: '序号',
      dataIndex: 'key',
      render: (text, record, index) => {
        return (index+1).toString();
      },
      width: 60,
      ellipsis: true,
    },
    {
      title: '模型名称',
      dataIndex: 'name',
      width: isSzseEnv?360:160,
      ellipsis: true,
      sorter: true,
      sortDirections: ['ascend', 'descend'],
      render: (text, record, index) => {
        return (<ModelNameColumn text={text} record={record} detailItem={detailItem} />);
      }
    },
    {
      title: '中文名称',
      dataIndex: 'cnName',
      width: isSzseEnv?420:160,
      ellipsis: true,
      sorter: true,
      sortDirections: ['ascend', 'descend'],
      render: (text, _, __) => {
        return (
          <Tooltip title={text||''}>
            <Text ellipsis={true}>{text||''}</Text>
          </Tooltip>
        )
      }
    },
    {
      title: '状态',
      dataIndex: 'state',
      width: 100,
      ellipsis: true,
      sorter: true,
      sortDirections: ['ascend', 'descend'],
      render: (_, record) => {

        let color = '';
        if (record?.state?.id === '1') {
          color = '#DE7777';
        } else if (record?.state?.id === '2') {
          color = '#779BDE';
        } else if (record?.state?.id === '4') {
          color = '#77DEBF';
        }

        return (
          <span>
            <span style={{ display: 'inline-block', width: 10, height: 10, borderRadius: 5, marginRight: 5, backgroundColor: color  }}></span>
            <span>{record?.state?.cnName||''}</span>
          </span>
        );
      }
    },
    {
      title: '创建人',
      dataIndex: 'editor',
      width: 100,
      ellipsis: true,
      sorter: true,
      sortDirections: ['ascend', 'descend'],
    },
    {
      title: '版本号',
      dataIndex: 'modifiedTs',
      width: 170,
      ellipsis: true,
      sorter: true,
      sortDirections: ['ascend', 'descend'],
      render: (_,record) => {
        return `V_${formatDate(record.modifiedTs)}`;
      }
    },
    // {
    //   title: '标签',
    //   dataIndex: 'tag',
    //   width: 200,
    //   onCell: (record) => ({ 
    //     onMouseEnter: event => {
    //       setMouseEnterKey(record.id);
    //     }, 
    //     onMouseLeave: event => {
    //       setMouseEnterKey(null);
    //     },
    //   }),
    //   render: (_,record) => {
    //     return (
    //       record.id===mouseEnterKey?<Tag styleType='complex' id={record.id} />:<Tag id={record.id} />
    //     );
    //   }
    // },
    {
      title: '模型描述',
      dataIndex: 'remark',
      ellipsis: true,
      sorter: true,
      sortDirections: ['ascend', 'descend'],
      render: (text, _, __) => {
        return (
          <Tooltip title={text||''} overlayClassName='tooltip-common'>
            <Text ellipsis={true}>{text||''}</Text>
          </Tooltip>
        );
      }
    },
  ];

  const pathColumn = {
    title: '路径',
    dataIndex: 'path',
    width: 120,
    ellipsis: true,
    sorter: true,
    sortDirections: ['ascend', 'descend'],
    render: (text, _, __) => {
      return (
        <Tooltip title={text||''}>
          <Text ellipsis={true}>{text||''}</Text>
        </Tooltip>
      )
    }
  };

  const [ columns, setColumns ] = useState([]);
  const [ includePathColumns, setIncludePathColumns ] = useState([]);
  const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
  const [ currentItem, setCurrentItem ] = useState(null);
  const { pageNum, pageSize } = pagination;
  
  const [modal, contextHolder] = Modal.useModal();

  const anchorId = getQueryParam(AnchorId, props.location.search);
  const anchorTimestamp = getQueryParam(AnchorTimestamp, props.location.search);

  const shouldScrollRef = useRef(false);

  useEffect(() => {

    if ((modelId||'') !== '') {
      window?.addEventListener("storage", modelEventChange);
    
      return () => {
        window?.removeEventListener("storage", modelEventChange);
      }
    } 
  
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {

    if ((modelId||'') === '') {
      onSelect && onSelect([]);
      
      if ((keyword||'') === '') {
        if (offset !== null) {
          const _pageNum = parseInt(offset/pageSize + ((offset%pageSize===0)?0:1));
          setPagination({...pagination, pageNum: _pageNum });
        } else {
          setPagination({...pagination, pageNum: 1 });
        }
      } else {
        setPagination({...pagination, pageNum: 1 });
      }
    } else {
      getCheckoutDataModel();
    }
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ catalogId, keyword, offset, modelState ]);

  useEffect(() => {
    if ((selectModelerIds||[]).length === 0) {
      setSelectedRowKeys([]);
      setSubSelectedRowKeys([]);
    }
  }, [selectModelerIds])

  useEffect(() => {

    if ((anchorId||'') !== '') {
      shouldScrollRef.current = true;
    }

    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [anchorTimestamp])

  useEffect(() => {
    if (shouldScrollRef.current) {
      SmoothScroll('a[href*="#"]');

      const _id = getQueryParam(AnchorId, props.location.search);
      var scroll = new SmoothScroll();
      var anchor = document.querySelector(`#data-model-${_id}`);

      if (anchor) {
        scroll.animateScroll(anchor);
        shouldScrollRef.current = false;
      }
    }
  })

  useEffect(() => {

    const newData = [...data];
    if (sortRule) {
      if (sortRule.order === 'ascend') {
        newData.sort((item1, item2) => {

          if (sortRule.field === 'state') {
            return (item1[sortRule.field]?.cnName||'').localeCompare(item2[sortRule.field]?.cnName||'');
          } else if (sortRule.field === 'modifiedTs') {
            return formatDate(item1[sortRule.field]).localeCompare(formatDate(item2[sortRule.field]));
          }

          return item1[sortRule.field].localeCompare(item2[sortRule.field]);
        })
      } else if (sortRule.order === 'descend') {
        newData.sort((item1, item2) => {
          if (sortRule.field === 'state') {
            return (item2[sortRule.field]?.cnName||'').localeCompare(item1[sortRule.field]?.cnName||'');
          } else if (sortRule.field === 'modifiedTs') {
            return formatDate(item2[sortRule.field]).localeCompare(formatDate(item1[sortRule.field]));
          }

          return item2[sortRule.field].localeCompare(item1[sortRule.field]);
        })
      } 
    }

    const _data = paginate(newData||[], pageNum, pageSize);

    setFilterData(_data);

    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data, pagination, sortRule])

  useEffect(() => {

    if (tableWidth) {
      let newColumns = [], newIncludePathColumns = [];

      let excludePathCols = [...cols];
      if ((modelId||'') !== '') {
        excludePathCols = cols.filter(item => item.dataIndex!=='key');
      }

      excludePathCols.forEach((column, index) => {
        const newColumn = {...column}; 
        if (!newColumn.width) {
          const rowWidth = (excludePathCols.reduce((preVal, col) => (col.width?col.width:0) + preVal, 0)) + 97; //展开50 勾选32 滚动条15
          
          if (tableWidth > rowWidth) {
            newColumn.width = (tableWidth-rowWidth)>200?(tableWidth-rowWidth):200;        
          } else {
            newColumn.width = 200;
          }
        }

        newColumns.push(newColumn);
      });

      const includePathCols = [...cols];
      includePathCols.splice(3, 0, pathColumn);

      includePathCols.forEach((column, index) => {
        const newColumn = {...column}; 
        if (!newColumn.width) {
          const rowWidth = (includePathCols.reduce((preVal, col) => (col.width?col.width:0) + preVal, 0)) + 97;
          
          if (tableWidth > rowWidth) {
            newColumn.width = (tableWidth-rowWidth)>200?(tableWidth-rowWidth):200;        
          } else {
            newColumn.width = 200;
          }
        }

        newIncludePathColumns.push(newColumn);
      });

      setColumns(newColumns);
      setIncludePathColumns(newIncludePathColumns);
    }

    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ tableWidth ])

  const modelEventChange = (e) => {
    if (e.key === 'modelChange') {
      getCheckoutDataModel();
    }
  }

  const getCheckoutDataModel = () => {
    dispatch({
      type: 'datamodel.getCheckoutDataModel',
      payload: {
        id: modelPid
      },
      callback: data => {
        setSubData(data?[data]:[]);
      },
      error: () => {

      }
    })
  }

  // const getDataModel = () => {
  //   dispatch({
  //     type: 'datamodel.getDataModel',
  //     payload: {
  //       id: modelId
  //     },
  //     callback: data => {
  //       setSubData(data?[data]:[]);
  //     },
  //     error: () => {

  //     }
  //   })
  // }

  const editItem = (record) => {
    onItemAction && onItemAction(record, 'edit');
  }

  const detailItem = (record) => {
    onItemAction && onItemAction(record, 'detail');
  }

  const deployAction = (record) => {
    onAutoCreateTable && onAutoCreateTable(record);
  }

  const stateAction = (record, action) => {
    modal.confirm({
      title: '提示!',
      content: `您确定要${action.cnName||''}该模型吗?`,
      onOk: () => {
        dispatch({
          type: 'datamodel.nextState',
          payload: {
            easyDataModelerDataModelId: record.id,
            actionId: action.id
          },
          callback: () => {
            showMessage('success', `模型${action.cnName||''}成功`);

            if ((modelId||'') === '') {
              onChange && onChange();

              const index = selectedRowKeys.findIndex((rowKey) => rowKey === record.id);
              if (index !== -1) {
                const newSelectedRowKeys = [...selectedRowKeys];
                newSelectedRowKeys.splice(index, 1);
                setSelectedRowKeys(newSelectedRowKeys);
                onSelect && onSelect(newSelectedRowKeys);
              }
            } else {
              if (action.id === '2') {
                onChange && onChange();
              } else {
                getCheckoutDataModel();
              }
            }
            
          }
        })
      }
    });
  }

  const deleteItem = (record) => {

    modal.confirm({
      title: '提示!',
      content: '您确定要删除该模型吗?',
      onOk: () => {
        dispatch({
          type: 'datamodel.deleteDataModel',
          payload: {
            params: {
              id: record.id
            }
          },
          callback: () => {
            showMessage('success', '模型删除成功');
            onChange && onChange();

            if ((modelId||'') ==='') {
              const index = selectedRowKeys.findIndex((rowKey) => rowKey === record.id);
              if (index !== -1) {
                const newSelectedRowKeys = [...selectedRowKeys];
                newSelectedRowKeys.splice(index, 1);
                setSelectedRowKeys(newSelectedRowKeys);
                onSelect && onSelect(newSelectedRowKeys);
              }
            }
            
          }
        })
      }
    });
  }

  const historyItem = (record) => {
    onHistory && onHistory(record.id);
  }

  const onSelectChange = keys => {
    setSelectedRowKeys(keys);

    if ((modelId||'') !== '') {
      onSubSelect && onSubSelect(keys, subData[0].id);
    } else {
      onSelect && onSelect([...subSelectedRowKeys, ...keys]);
    }
  };

  const onSubSelectChange = (keys, id) => {
    if ((keys||[]).length === 0) {
      const index = subSelectedRowKeys.findIndex((rowKey) => rowKey === id);
      const newSubSelectedRowKeys = [...subSelectedRowKeys];
      newSubSelectedRowKeys.splice(index, 1);
      setSubSelectedRowKeys(newSubSelectedRowKeys);
      onSelect && onSelect([...newSubSelectedRowKeys, ...selectedRowKeys]);
    } else {
      const newSubSelectedRowKeys = [...subSelectedRowKeys, id];
      onSelect && onSelect([...newSubSelectedRowKeys, ...selectedRowKeys]);
    }
  }

  const handleResize = index => (e, { size }) => {
    let nextColumns = [...columns];

    if ((modelId||'')==='' && (view==='state'||(keyword||'')!=='')) {
      nextColumns = [...includePathColumns];
    }
    
    nextColumns[index] = {
      ...nextColumns[index],
      width: size.width,
    };

    if ((modelId||'')==='' && (view==='state'||(keyword||'')!=='')) {
      setIncludePathColumns(nextColumns);
    } else {
      setColumns(nextColumns);
    }
  };

  const onTableChange = (pagination, filters, sorter, extra) => {
    if (sorter) {
      setSortRule(sorter);
    }
  }

  const rowSelection = {
    selectedRowKeys,
    onChange: onSelectChange,
    hideSelectAll: (modelId||'') !=='',
  };

  const classes = classnames('model-table', {
    'model-table-sub': modelId
  });  

  let expandable = undefined;
  if (!modelId) {
    let needExpand = false;
    (filterData||[]).forEach(record => {
      if (record?.alreadyCheckedOut) {
        needExpand = true;
      }
    })

    if (needExpand) {
      expandable = {
        expandedRowRender: record => <ModelTable 
          modelId={record?.checkedOutId}
          modelPid={record?.id}
          onSubSelect={onSubSelectChange}
          {...props} 
        />,
        expandIcon: ({ expanded, onExpand, record }) => {
          if (!record?.alreadyCheckedOut) return null;

          return expanded ? <UpOutlined style={{ fontSize: 10 }} onClick={e => onExpand(record, e)} /> : <DownOutlined style={{ fontSize: 10 }} onClick={e => onExpand(record, e)} />
        },
        rowExpandable: record => {
          return record?.alreadyCheckedOut;
        }
      };
    }
  } else {
    expandable = {
      expandedRowRender: record => <></>,
      expandIcon: ({ expanded, onExpand, record }) => {
        return null;
      },
      rowExpandable: record => {
        return false;
      }
    }
  }

  const displayMenu = (e) => {
    show(e);
  }

  const handleItemClick = ({ event, props, data, triggerEvent }) => {
    const key = event.currentTarget.id;

    if (key === 'edit') {
      editItem(currentItem);
    } else if (key === 'delete') {
      deleteItem(currentItem);
    } else if (key === 'history') {
      historyItem(currentItem);
    } else if (key === 'copy') {
      window.open(`/data-govern/data-model-action?${Action}=add&${CatalogId}=${(view==='dir')?(catalogId||''):''}&${ModelerId}=${currentItem.id}`);
    } else if (key === 'createTable') {
      deployAction(currentItem);
    } else if (key.indexOf('action') !== -1) {
      const index = (key.split('-'))[1];
      const action = currentItem?.state?.supportedActions[index];
      stateAction(currentItem, action);
    }
  }

  const mergedColumns = () => {
    let newColumns = [...columns];
    if ((modelId||'')==='' && (view==='state'||(keyword||'')!=='')) {
      newColumns = [...includePathColumns];
    }

    return (
      newColumns.map((col, index) => ({
        ...col,
        onHeaderCell: column => ({
          width: column.width,
          onResize: handleResize(index),
        }),
      }))
    );
  }

  let disableEdit = false, disableDelete = false, editTip = '', deleteTip = '', editMenuTitle = '编辑';

  if (!currentItem?.editable && currentItem?.state?.id!=='4') {
    disableEdit = true;

    if (currentItem?.state?.id === '2') {
      editTip = '待发布的模型不允许编辑';
    }
  }

  if (!currentItem?.permitCheckOut && currentItem?.state?.id==='4') {
    disableEdit = true;
    editTip = `${currentItem.holder||''}正在编辑中, 不允许再编辑`;
    editMenuTitle = `编辑(${currentItem.holder||''}正在编辑中)`;
  }

  if (!currentItem?.deletable) {
    disableDelete = true;

    if (currentItem?.state?.id === '2') {
      deleteTip = '待发布的模型不允许删除';
    } else if (currentItem?.state?.id === '4') {
      deleteTip = '已发布的模型不允许删除';
    }
  }

  return (
    <div className={classes}>
      <ResizeObserver
        onResize={({ width }) => {
          setTableWidth(width);
        }}
      >
        <Table
          rowSelection={rowSelection} 
          components={{
            header: {
              cell: ResizeableHeaderCell,
            }
          }}
          columns={mergedColumns()}
          rowKey={'id'}
          dataSource={modelId?(subData||[]):(filterData||[])}
          pagination={false}
          size={modelId?'small':'default'}
          onRow={(record, index) => {
            return {
              id: `data-model-${record?.id}`,
              style: { backgroundColor: (record?.id===anchorId)?'#e7f7ff':'transparent' },
              onContextMenu: event => {
                setCurrentItem(record);
                displayMenu(event);
              },
            }
          }}
          scroll={{ y: modelId?null:((filterData||[]).length===0?null:'calc(100vh - 121px - 57px - 24px - 38px - 44px)') }}
          onChange={onTableChange}
          expandable={expandable}
        />
      </ResizeObserver>
      {
        !modelId && (data||[]).length>0 && <Pagination
          className="text-center mt-3"
          showSizeChanger
          showQuickJumper
          onChange={(_pageNum, _pageSize) => {
            setPagination({ pageNum: _pageNum, pageSize: _pageSize || 20 });
          }}
          onShowSizeChange={(_pageNum, _pageSize) => {
            setPagination({ pageNum: 1, pageSize: _pageSize });
          }}
          current={pageNum}
          pageSize={pageSize}
          defaultCurrent={1}
          total={(data||[]).length}
          pageSizeOptions={[10,20,50]}
          showTotal={total => `共 ${total} 条`}
        />
      }
      <RcMenu id={MENU_ID}>
        <RcItem id="edit" disabled={disableEdit} onClick={handleItemClick}>
          <Tooltip title={editTip}>
          { editMenuTitle }
          </Tooltip>
        </RcItem>
        <RcItem id="delete" disabled={disableDelete} onClick={handleItemClick}>
          <Tooltip title={deleteTip}>
            删除
          </Tooltip>
        </RcItem>
        <RcItem id="history" onClick={handleItemClick}>
          历史版本
        </RcItem>
        <RcItem id="copy" onClick={handleItemClick}>
          复制模型
        </RcItem>
        {
          (currentItem?.state?.supportedActions||[]).length>0 && currentItem?.state?.supportedActions.map((item, index) => {
            return (
              <RcItem id={`action-${index}`} onClick={handleItemClick}>
              {item.cnName||''}
              </RcItem>
            );
          }) 
        }
        {
          currentItem?.deployable && <RcItem id='createTable' onClick={handleItemClick}>
          建表
          </RcItem>
        }

      </RcMenu>
      { contextHolder }
    </div>
  );
}

export default ModelTable;