import React from 'react';
import { CnCardItems, CnBox, CnButton, CnIcon } from '@cainiaofe/cn-ui-m';
import {
  calculateTextExprValue,
  calculateWaitComponentList,
  executeFunction,
  executeObjectExpr,
  getRealizeValue,
  getRealRequestUrl,
  getRealResponse,
  getRunTimeItem,
  handleDesignMokelayUrl,
  handleI18nLabel,
  handleListI18nLabel,
  isArrayNotEmpty,
  isDesignMode,
  isEmptyButNotZero,
  isRequestConfig,
  makeButtons,
  renderIcon,
  setDataToDs,
  transDataSourceToMap,
  transProxyToObject,
} from '@/common/util/util';
import {
  CnPageRequestFinish,
  CnTableRequestFinish,
  emitEvent,
  onEvent,
} from '@/common/util/event-name';
import {
  handleRequestParams,
  makeRequest,
  transRequestConfigToRemote,
} from '@/common/manager/request';
import { allCellMap, getRunTimeCell } from '@/common/manager/cell';
import {
  _bindFilterData,
  _columnInfo,
  _getBindFilterData,
  _getContext,
  _selectedRowKeys,
  _selectedRowRecords,
  _state,
  _tableRef,
  _tableResponse,
} from '@/common/util/biz-component-prop-name';
import { getButtonAction, getItem } from '@/common/manager/button';
import { ButtonPosition } from '@/type/button-position';
import $i18n from 'panda-i18n';
import {
  __dataSource__,
  __filterValue__,
  __formValue__,
  __paging__,
  __selectedRowKeys__,
  __selectedRowRecords__,
  __tableColumns__,
  __tableCurrentRow__,
  __tableData__,
  __tableExtra__,
  __totalCount__,
} from '@/common/util/expr-const';
import isPlainObject from 'lodash/isPlainObject';
import cloneDeep from 'lodash/cloneDeep';
import { formUrlencoded } from '@/common/util/const';
import qs from 'query-string';
import set from 'lodash/set';
import isEmpty from 'lodash/isEmpty';

const CnDownload = () => {
  return null;
};
const CnOSSImport = () => {
  return null;
};

const CnExport = () => {
  return null;
};
const CnBalloon = () => {
  return null;
};

class CnTable extends React.Component {
  constructor(props) {
    super(props);
    this.remoteInstance = CnCardItems?.createRemoteInstance?.();
    const tempState = {
      allEnumMap: {},
      tableDataSource: undefined,
    };
    if (isArrayNotEmpty(props?.openKeys)) {
      tempState.openKeys = [...props.openKeys];
    }
    this.state = tempState;
  }

  setTableProps = (config) => {
    const { dataSource } = config || {};
    if (Array.isArray(dataSource)) {
      this.setState({
        tableDataSource: dataSource,
      });
    }
  };

  componentDidMount() {
    this.setEnumMap();
    onEvent(CnPageRequestFinish, () => {
      this.setEnumMap();
    });
  }

  setEnumMap = () => {
    const isDesign = isDesignMode(this.props);
    const { _context, columns } = this.props;
    const enumPromiseList = [];
    const allEnumMap = {};
    if (Array.isArray(columns) && columns.length > 0) {
      for (const item of columns) {
        const { dataIndex, format, options = {} } = item || {};
        if (dataIndex && format === 'enumeration') {
          const { enumDataOrigin, enumRequestConfig, enumDataSource } = options;
          if (enumDataOrigin === 'request' && enumRequestConfig?.url) {
            enumPromiseList.push(
              makeRequest({
                buttonConfig: {
                  options: {
                    requestConfig: enumRequestConfig,
                  },
                },
                state: _context?.state,
                needSuccessToast: false,
                isDesign,
                urlParamsDataSource: this.getUrlParams(),
              }).then((res) => {
                return {
                  dataIndex,
                  data: getRealResponse(res)?.data,
                };
              }),
            );
          } else if (enumDataOrigin === 'static') {
            if (Array.isArray(enumDataSource) && enumDataSource?.length > 0) {
              allEnumMap[dataIndex] = transDataSourceToMap(enumDataSource);
            } else if (typeof enumDataSource === 'function') {
              const temp = executeFunction(enumDataSource, _context?.state);
              if (Array.isArray(temp) && temp?.length > 0) {
                allEnumMap[dataIndex] = transDataSourceToMap(temp);
              }
            } else {
              const temp = calculateTextExprValue(enumDataSource, {
                state: _context?.state,
              });
              if (Array.isArray(temp) && temp?.length > 0) {
                allEnumMap[dataIndex] = transDataSourceToMap(temp);
              }
            }
          }
        }
      }
      if (enumPromiseList.length > 0) {
        Promise.allSettled(enumPromiseList).then((res) => {
          if (res.length > 0) {
            res.forEach((item3) => {
              if (item3?.value?.dataIndex && item3?.value?.data?.length > 0) {
                allEnumMap[item3?.value?.dataIndex] = transDataSourceToMap(
                  item3?.value?.data,
                );
              }
            });
          }
          this.setState({
            allEnumMap,
          });
        });
      } else if (Object.keys(allEnumMap).length > 0) {
        this.setState({
          allEnumMap,
        });
      }
    }
  };

  load = () => {
    this.setState({
      tableDataSource: undefined,
    });
    this.remoteInstance?.refresh?.();
  };

  tableLoad = () => {
    this.remoteInstance?.load?.();
  };

  getRemoteOperation = () => {
    return this.remoteInstance?.remoteOperation;
  };

  dynamicRegisterFormat = (data) => {
    if (data) {
      const { tableColumns = [] } = data;
      if (tableColumns?.length > 0) {
        const formatMap = {};
        tableColumns.forEach((item) => {
          const { format, dataIndex } = item || {};
          if (format && !allCellMap[format]) {
            const componentDefine = getRunTimeCell(format);
            if (componentDefine) {
              let { component } = componentDefine;
              component = getRealizeValue(component);
              if (component && typeof component === 'function') {
                formatMap[format] = (column) => {
                  return {
                    cell: (value, index, record) => {
                      const com = React.createElement(component, {
                        [_columnInfo]: column,
                        cellConfig: column,
                        value,
                        record,
                        index,
                        enumMap: this.state.allEnumMap[column?.dataIndex],
                        [_tableRef]: this,
                        // _context,
                      });
                      if (com) {
                        return com;
                      }
                      return '-';
                    },
                    enableAutoWidth: false,
                  };
                };
              }
            }
          }
        });
        if (Object.keys(formatMap).length > 0) {
          // UICnTable?.registerFormat(formatMap)
        }
      }
    }
  };

  // 处理数据源
  handleDesignMode = (tableProps = {}, isDesign) => {
    if (isDesign) {
      const { remote, requestConfig, columns } = tableProps;
      // const newData = {}
      // if(dataSource.length === 0 && columns.length > 0){
      //   columns.forEach(item=>{
      //     const {dataIndex,format} = item;
      //     newData[dataIndex] = 'mock数据'
      //   })
      //   tableProps.dataSource = [newData]
      // }
      // tableProps.remote = {}

      // 如果table配置了remote，那么强制将dataSource设置为空，并且设置remote.url的域名为预发mokelay的域名
      if (remote && remote.url && remote.serviceType === 'mokelay') {
        tableProps.remote = {
          ...tableProps.remote,
          url: handleDesignMokelayUrl(remote.url),
        };
        // tableProps.dataSource = undefined
      }

      handleListI18nLabel(tableProps?.columns, 'title');
      handleListI18nLabel(tableProps?.operateColumn?.buttons, 'children');
      handleListI18nLabel(tableProps?.toolbar?.batchArea, 'children');
      handleListI18nLabel(tableProps?.toolbar?.toolArea, 'children');
      if (tableProps?.emptyContent) {
        tableProps.emptyContent = handleI18nLabel(tableProps.emptyContent);
      }

      if (!requestConfig?.url && isArrayNotEmpty(columns)) {
        const tempData = {};
        columns.forEach((item) => {
          const { dataIndex } = item;
          if (dataIndex) {
            tempData[dataIndex] = 'mock数据';
          }
        });
        tableProps.dataSource = [tempData];
      }
    }
  };

  /**
   * 处理操作列
   */
  handleColumns = (columns = []) => {
    const newColumnMap = {};
    const result = [];
    columns.forEach((item) => {
      const { parent } = item || {};
      const newColumn = this.makeColumnItem(item);
      if (newColumn) {
        if (newColumn?.dataIndex) {
          newColumnMap[newColumn.dataIndex] = newColumn;
        }
        if (parent && newColumnMap[parent]) {
          if (Array.isArray(newColumnMap[parent].children)) {
            newColumnMap[parent].children.push(newColumn);
          } else {
            newColumnMap[parent].children = [newColumn];
          }
        } else {
          result.push(newColumn);
        }
      }
    });
    return result;
  };

  makeColumnItem = (item) => {
    if (item) {
      const { _context } = this.props;
      const isDesign = isDesignMode(this.props);
      const {
        dataIndex,
        format,
        optType,
        options = {},
        cellRender,
      } = item || {};
      const result = {
        ...item,
        cellRender: undefined,
      };
      if (format === 'date-time') {
        result.dateHasSecond = true;
      }

      if (typeof result.hidden === 'boolean') {
        return () => {
          return result.hidden;
        };
      } else if (typeof result.hidden === 'function') {
        return (record, index) => {
          return executeFunction(
            result?.hidden,
            record,
            _context?.state,
            index,
          );
        };
      }

      if (format) {
        const componentDefine = getRunTimeCell(format);
        if (componentDefine) {
          let { component } = componentDefine;
          component = getRealizeValue(component);
          if (component && typeof component === 'function') {
            result.cell = (value, index, record) => {
              const com = React.createElement(component, {
                ...options,
                cellConfig: item,
                value,
                record,
                index,
                _context,
                enumMap: this.state.allEnumMap[dataIndex],
                [_tableRef]: this,
              });
              if (com) {
                return com;
              }
              return '-';
            };
            result.enableAutoWidth = false;
          }
        }
      }
      if (optType) {
        const action = getButtonAction({
          ...item,
          position: ButtonPosition.tableCell,
        });
        if (action && !isDesign) {
          result.getCellProps = (value, rawData, rawIndex) => {
            const temp = {};
            if (isEmptyButNotZero(value)) {
            } else {
              temp.onClick = () => {
                if (optType === 'dialog' || optType === 'flowAction') {
                  if (isPlainObject(rawData)) {
                    this.setDataSource({
                      [__tableCurrentRow__]: rawData,
                    });
                  }
                }
                action({
                  buttonConfig: item,
                  record: rawData,
                  index: rawIndex,
                  value,
                  state: _context?.state,
                  urlParamsDataSource: this.getUrlParams(),
                  recordDataSource: rawData,
                  extraParamList: [rawIndex],
                  _context,
                  position: ButtonPosition.tableCell,
                });
              };
            }
            if (optType) {
              temp.className = 'cn-table-link-cell';
            }
            return temp;
          };
        }
      }
      if (typeof cellRender === 'function') {
        result.cell = cellRender;
      }
      return result;
    }
  };

  handleOperateButtonExpr = (expr, state) => {
    if (typeof expr === 'boolean') {
      return () => {
        return expr;
      };
    } else if (typeof expr === 'function') {
      return (record, index) => {
        return expr?.(record, state, index);
      };
    } else if (typeof expr === 'string' && expr.length > 0) {
    } else if (isPlainObject(expr)) {
      return (record, index) => {
        return executeObjectExpr(expr, {
          [__tableCurrentRow__]: record || {},
          [__dataSource__]: state || {},
        });
      };
    }
    return expr;
  };
  //
  // handleToolbarButtonExpr = (expr, state) => {
  //   if (typeof expr === 'boolean') {
  //     return () => {
  //       return expr;
  //     };
  //   } else if (typeof expr === 'function') {
  //     return () => {
  //       return expr?.(this.getFilterParams(), state);
  //     };
  //   } else if ((typeof expr === 'string' && expr.length > 0) || isPlainObject(expr)) {
  //     return ()=>{
  //       const filterParams = this.getFilterParams();
  //       return executeObjectExpr(expr, {
  //         [__formValue__]: filterParams,
  //         [__filterValue__]: filterParams,
  //         [__dataSource__]: state || {},
  //       }, filterParams, state || {})
  //     }
  //   }
  //   return expr;
  // };

  handleOperateButtons = (buttons = []) => {
    const isDesign = isDesignMode(this.props);
    const { _context } = this.props;
    return buttons.map((item, index) => {
      const {
        primaryKey,
        optType,
        options = {},
        children,
        hidden,
        disabled,
        ...rest
      } = item;
      const isHidden = this.handleOperateButtonExpr(hidden, _context?.state);
      const isDisabled = this.handleOperateButtonExpr(
        disabled,
        _context?.state,
      );
      const temp = {
        ...rest,
        hidden: isHidden,
        disabled: isDisabled,
        children,
      };
      const action = getButtonAction({
        ...item,
        position: ButtonPosition.tableOperate,
      });
      const componentDefine = getRunTimeItem(optType);
      if (action) {
        if (!isDesign) {
          const tempButtonConfig = cloneDeep(item);
          temp.onClick = (e, record, index) => {
            if (isPlainObject(record)) {
              this.setDataSource({
                [__tableCurrentRow__]: record,
              });
            }
            action({
              position: ButtonPosition.tableOperate,
              componentProps: this.props,
              buttonConfig: tempButtonConfig,
              e,
              record,
              index,
              _context,
              tableRef: this,
              state: _context?.state,
              urlParamsDataSource: this.getUrlParams(),
              recordDataSource: record,
              extraParamList: [index],
              [_getContext]: () => {
                return _context;
              },
            });
          };
          const { needConfirm, confirmInfo } = options || {};
          if (
            optType === 'request' &&
            needConfirm &&
            confirmInfo?.confirmShowType === 'balloon'
          ) {
            // const commonParams = this.getCommonParams();
            // const oldClick = temp.onClick;
            // temp.children = (record,index)=>{
            //   return <CnConfirmButton
            //     dialogTitle={calculateTextExprValue(confirmInfo.title, commonParams)}
            //     dialogContent={calculateTextExprValue(confirmInfo.content, commonParams)}
            //     text
            //     isBalloon
            //     type={'primary'}
            //     btnContent={children}
            //     balloonProps={{
            //       align:'tr'
            //     }}
            //     successMsg={false}
            //     onConfirmSuccess={oldClick?.bind(this, null, record,index)}
            //   />
            // }
            // tempButtonConfig.options.needConfirm = false
            // temp.onClick = undefined
          }
        }
      } else if (componentDefine?.component) {
        const component = getRealizeValue(componentDefine.component);
        if (component) {
          temp.children = (record, index) => {
            return React.createElement(component, {
              ...options,
              record,
              index,
              buttonConfig: item,
              children,
              _context,
              [_tableRef]: this,
              [_getBindFilterData]: this.getFilterParams,
              [_getContext]: () => {
                return _context;
              },
            });
          };
        }
      }
      return temp;
    });
  };

  handleRowSelection = (rowSelection) => {
    const { selectType } = rowSelection || {};
    const { _context, value, useDetailValue } = this.props;
    const result = { ...rowSelection, useDetailValue };
    if (typeof result?.isDisabled === 'function') {
      const originIsDisabledFunc = result.isDisabled;
      result.isDisabled = (
        row,
        rowIndex,
        selectedRowKeys,
        selectedRowRecords,
      ) => {
        return originIsDisabledFunc(
          row,
          rowIndex,
          selectedRowKeys,
          selectedRowRecords,
          _context?.state,
        );
      };
    } else {
      delete result?.isDisabled;
    }
    result.type = selectType;
    if (isArrayNotEmpty(value)) {
      result.selectedRowKeys = value;
    }
    return result;
  };

  // 处理工具栏按钮
  handleToolbar = (toolbar) => {
    const result = {};
    if (toolbar) {
      const { batchArea = [], toolArea = [], settings = [] } = toolbar;
      if (batchArea.length > 0) {
        result.batchArea = batchArea
          .map((item) => {
            return this.makeButton(item, ButtonPosition.tableBatchArea);
          })
          .filter((item) => item);
      }
      if (toolArea.length > 0) {
        result.toolArea = toolArea
          .map((item) => {
            return this.makeButton(item, ButtonPosition.tableToolArea);
          })
          .filter((item) => item);
      }
      if (settings.length > 0) {
        result.settings = settings;
      }
    }
    return result;
  };

  getDownloadProps = (data, extraConfig) => {
    const { getExtraParam } = extraConfig || {};
    let downloadProps;
    if (typeof data === 'string') {
      downloadProps = {
        url: data,
      };
    } else if (isRequestConfig(data)) {
      downloadProps = {
        service: transRequestConfigToRemote({
          requestConfig: data,
          isDesign: isDesignMode(this.props),
          ...this.getCommonParams(),
          getExtraParam,
        }),
      };
    }
    return downloadProps;
  };

  getCommonParams = () => {
    const { _context } = this.props;
    return {
      state: _context?.state,
      recordDataSource: this.getFilterParams(),
      urlParamsDataSource: this.getUrlParams(),
      isDesign: isDesignMode(this.props),
    };
  };

  makeButton = (item, area, extraConfig) => {
    const { buttonProps } = extraConfig || {};
    const isDesign = isDesignMode(this.props);
    const filterParams = this.getFilterParams();
    const { _context, _dataSource } = this.props;
    const {
      iconType,
      primaryKey,
      optType,
      options = {},
      children,
      disabled,
      hidden,
      buttonHoverInfo,
      ...rest
    } = item;
    const remoteOperation = this.getRemoteOperation();
    const innerInfo = remoteOperation?.current?.innerInfo;
    let result = {
      ...rest,
      children,
    };
    const action = getButtonAction({ ...item, position: area });
    const getRenderDom = getItem(area, optType, 'getRenderDom');
    const componentDefine = getRunTimeItem(optType);
    const isHidden = executeObjectExpr(
      hidden,
      {
        [__formValue__]: filterParams,
        [__filterValue__]: filterParams,
        [__dataSource__]: _context?.state,
      },
      filterParams,
      _context?.state,
    );
    let isDisabled;
    if (action) {
    } else {
      isDisabled = executeObjectExpr(
        disabled,
        {
          [__formValue__]: filterParams,
          [__filterValue__]: filterParams,
          [__dataSource__]: _context?.state,
        },
        filterParams,
        _context?.state,
        _dataSource?.[__selectedRowKeys__] || [],
        _dataSource?.[__selectedRowRecords__] || [],
      );
    }
    if (isHidden) {
      return null;
    }
    if (optType === 'download') {
      const { url } = options;
      return (selectedRowKeys, selectedRowRecords) => {
        let downloadProps;
        if (typeof url === 'function') {
          downloadProps = {
            url: executeFunction(url, filterParams, _context?.state),
          };
        } else {
          downloadProps = this.getDownloadProps(url, {
            getExtraParam: () => {
              const { currentPage, pageSize } = innerInfo?.pageInfo || {};
              return {
                currentPage,
                pageSize,
              };
            },
          });
        }
        return (
          <CnDownload
            buttonText={children}
            buttonProps={{
              ...buttonProps,
              type: item?.type,
              disabled: isDisabled,
            }}
            {...downloadProps}
          />
        );
      };
    } else if (optType === 'ossImport') {
      const {
        createService,
        pollingService,
        uploadService,
        templateUrl,
        hideLoop,
        dialogDescription,
      } = options;
      return (selectedRowKeys, selectedRowRecords) => {
        const extraProps = {
          autoImport: true,
          hideLoop,
        };
        const uploadMsgSlot = [];
        let realDes = dialogDescription;
        if (typeof dialogDescription === 'function') {
          realDes = executeFunction(
            dialogDescription,
            this.getFilterParams(),
            _context?.state,
            selectedRowKeys,
            selectedRowRecords,
          );
        }
        const downloadProps = this.getDownloadProps(templateUrl);
        if (downloadProps) {
          uploadMsgSlot.push(
            <CnBox direction='row' align='center'>
              {$i18n.get({ id: 'PleaseDownload', dm: '请下载' })}&nbsp;
              <CnDownload
                buttonProps={{
                  text: true,
                  type: 'primary',
                  disabled: isDisabled,
                }}
                buttonText={$i18n.get({
                  id: 'ImportFileTemplate',
                  dm: '导入文件模板',
                })}
                {...downloadProps}
              />
            </CnBox>,
          );
        }
        if (realDes) {
          uploadMsgSlot.push(
            <CnBox direction='row' align='center'>
              {realDes}
            </CnBox>,
          );
        }
        if (isArrayNotEmpty(uploadMsgSlot)) {
          extraProps.uploadMsgSlot = uploadMsgSlot;
        }
        return (
          <CnOSSImport
            buttonProps={{
              ...buttonProps,
              disabled: isDisabled,
              type: item?.type,
            }}
            {...extraProps}
            buttonText={children}
            onSuccess={(res) => {
              if (res?.status !== 'EXECUTING') {
                this.load();
              }
            }}
            uploadProps={{
              service: transRequestConfigToRemote({
                requestConfig: uploadService,
                handleParams: () => {
                  return {
                    selectedRowKeys,
                    selectedRowRecords,
                  };
                },
                ...this.getCommonParams(),
              }),
              description: '',
            }}
            createService={(res) => {
              return makeRequest({
                handleParams: () => {
                  return {
                    key: res,
                  };
                },
                buttonConfig: {
                  options: {
                    requestConfig: createService,
                  },
                },
                ...this.getCommonParams(),
                needSuccessToast: false,
                isDesign,
              }).then((res) => {
                return getRealResponse(res)?.data;
              });
            }}
            pollingService={transRequestConfigToRemote({
              requestConfig: pollingService,
              ...this.getCommonParams(),
            })}
          />
        );
      };
    } else if (optType === 'export') {
      const {
        createService,
        pollingService,
        hideLoop,
        needRename,
        defaultJobName,
      } = options;
      const extraProps = {};
      if (
        needRename === true &&
        typeof defaultJobName === 'string' &&
        defaultJobName.length > 0
      ) {
        extraProps.renameDialogProps = {
          defaultJobName,
        };
      }
      return (selectedRowKeys, selectedRowRecords) => {
        return (
          <CnExport
            {...extraProps}
            autoDownload
            needRename={needRename}
            hideLoop={hideLoop}
            buttonText={children}
            buttonProps={{
              ...buttonProps,
              disabled: isDisabled,
              type: item?.type,
            }}
            showAsyncDialog
            createService={(fileName) => {
              let jobName = fileName || {};
              if (typeof fileName === 'string') {
                jobName = {
                  jobName: fileName,
                };
              }
              return makeRequest({
                handleParams: () => {
                  const filterParams = this.getFilterParams();
                  let temp = {
                    selectedRowKeys,
                    selectedRowRecords,
                    ...jobName,
                  };
                  if (isPlainObject(filterParams)) {
                    temp = {
                      ...filterParams,
                      ...temp,
                    };
                  }
                  return temp;
                },
                buttonConfig: {
                  options: {
                    requestConfig: createService,
                  },
                },
                ...this.getCommonParams(),
                needSuccessToast: false,
                isDesign,
              }).then((res) => {
                return getRealResponse(res)?.data;
              });
            }}
            pollingService={transRequestConfigToRemote({
              requestConfig: pollingService,
            })}
          />
        );
      };
    } else if (typeof getRenderDom === 'function') {
      result = (selectedRowKeys, selectedRowRecords) => {
        return getRenderDom({
          ...item,
          state: _context?.state,
          position: area,
          selectedRowKeys,
          selectedRowRecords,
          tableRef: this,
          isDesign,
          makeButton: this.makeButton,
          buttonConfig: item,
          recordDataSource: filterParams,
        });
      };
    }
    if (action) {
      if (result.children && iconType && typeof iconType === 'string') {
        result.children = [
          <span style={{ marginRight: '4px' }}>{renderIcon(iconType)}</span>,
          result.children,
        ];
      }
      result.onClick = (e, selectedRowKeys, selectedRowRecords) => {
        action({
          buttonConfig: item,
          _context,
          selectedRowKeys,
          selectedRowRecords,
          tableRef: this,
          componentProps: this.props,
          position: area,
          ...this.getCommonParams(),
        });
      };
      result.disabled = (selectedRowKeys, selectedRowRecords) => {
        // if(area === ButtonPosition.tableBatchArea && !(selectedRowKeys?.length > 0)) {
        //   return true;
        // }
        return executeObjectExpr(
          disabled,
          {
            [__formValue__]: filterParams,
            [__filterValue__]: filterParams,
            [__dataSource__]: _context?.state,
          },
          filterParams,
          _context?.state,
          selectedRowKeys || [],
          selectedRowRecords || [],
        );
      };
      let needHover;
      let hoverInfo;
      if (options?.needHover && options?.hoverInfo) {
        needHover = options?.needHover;
        hoverInfo = options?.hoverInfo;
      } else {
        needHover = buttonHoverInfo?.needHover;
        hoverInfo = buttonHoverInfo?.hoverInfo;
      }
      if (needHover && (hoverInfo?.title || hoverInfo?.content)) {
        const originalResult = { ...result };
        result = (selectedRowKeys, selectedRowRecords) => {
          const commonParams = this.getCommonParams();
          const title = calculateTextExprValue(hoverInfo?.title, {
            ...commonParams,
            extraParamList: [selectedRowKeys, selectedRowRecords],
          });
          const content = calculateTextExprValue(hoverInfo?.content, {
            ...commonParams,
            extraParamList: [selectedRowKeys, selectedRowRecords],
          });
          let tempDom = (
            <CnButton
              {...originalResult}
              disabled={originalResult?.disabled?.(selectedRowKeys)}
              onClick={(e) => {
                originalResult?.onClick?.(
                  e,
                  selectedRowKeys,
                  selectedRowRecords,
                );
              }}
            />
          );
          if (title || content) {
            const oldDom = (
              <div style={{ display: 'inline-block' }}>{tempDom}</div>
            );
            tempDom = (
              <CnBalloon trigger={oldDom} title={title} closable={false}>
                {content}
              </CnBalloon>
            );
          }
          return tempDom;
        };
      }
      return result;
    } else if (componentDefine?.component) {
      const component = getRealizeValue(componentDefine.component);
      if (component) {
        result = (selectedRowKeys, selectedRowRecords) => {
          return React.createElement(component, {
            ...options,
            selectedRowKeys,
            selectedRowRecords,
            [_selectedRowKeys]: selectedRowKeys,
            [_selectedRowRecords]: selectedRowRecords,
            [_state]: _context?.state,
            buttonConfig: item,
            children,
            _context,
            [_bindFilterData]: this.getFilterParams(),
            [_getBindFilterData]: this.getFilterParams,
            tableRef: this,
            disabled: isDisabled,
            hidden: isHidden,
            [_getContext]: () => {
              return _context;
            },
          });
        };
      }
      return result;
    }
    return result;
  };

  getFilterParams = () => {
    let filterParams = {};
    const { _context, _bindFilterDataSourceName } = this.props;
    if (_context && _bindFilterDataSourceName) {
      filterParams = transProxyToObject(
        _context?.state?.[_bindFilterDataSourceName],
      );
    }
    return filterParams;
  };

  getUrlParams = () => {
    const { _context } = this.props;
    return _context?.state?.urlParams || {};
  };

  handleRowDetail = (rowDetail) => {
    if (typeof rowDetail?.renderDetail === 'string') {
      const componentDefine = getRunTimeItem(rowDetail.renderDetail);
      if (componentDefine?.component) {
        const component = getRealizeValue(componentDefine.component);
        if (component) {
          const { _context } = this.props;
          return {
            rowDetail: {
              renderDetail: (record, index) => {
                return React.createElement(component, {
                  record,
                  index,
                  [_state]: _context?.state,
                  [_tableRef]: this,
                  _context,
                });
              },
            },
          };
        }
      }
    }
    return {};
  };

  handleSelectChange = (selectType, selectedRowKeys, selectedRowRecords) => {
    const { onChange } = this.props;
    let realSelectedRowKeys = selectedRowKeys;
    let realSelectedRowRecords = selectedRowRecords;
    if (selectType === 'single') {
      realSelectedRowKeys = [selectedRowKeys];
      realSelectedRowRecords = [selectedRowRecords];
    }
    this.setDataSource({
      [__selectedRowKeys__]: realSelectedRowKeys || [],
      [__selectedRowRecords__]: realSelectedRowRecords || [],
    });
    if (typeof onChange === 'function') {
      onChange(realSelectedRowKeys);
    }
  };

  setDataSource = (data) => {
    const { _context, _dataSource, _dataSourceName } = this.props;
    setDataToDs({
      _context,
      _dataSource,
      _dataSourceName,
      data,
    });
  };

  sendRequestFinishEvent = (newRes) => {
    const { _context } = this.props;
    emitEvent(CnTableRequestFinish, {
      [_getContext]: () => {
        return _context;
      },
      [_tableRef]: this,
      [_getBindFilterData]: this.getFilterParams,
      [_tableResponse]: newRes,
    });
  };

  setTableInfo = (data) => {
    const remoteOperation = this.getRemoteOperation();
    const newData = {};
    if (isPlainObject(data)) {
      const { paging, tableData, extra } = data;
      const { totalCount } = data.paging || {};
      if (typeof totalCount === 'number') {
        newData[__totalCount__] = totalCount;
      }
      if (isPlainObject(paging)) {
        newData[__paging__] = paging;
      }
      if (Array.isArray(tableData)) {
        newData[__tableData__] = tableData;
      }
      if (isPlainObject(extra)) {
        newData[__tableExtra__] = extra;
      }
      const innerInfo = remoteOperation?.current?.innerInfo;
      if (innerInfo) {
        const { columns } = innerInfo;
        if (Array.isArray(columns)) {
          newData[__tableColumns__] = columns;
        }
      }
    }
    if (Object.keys(newData).length > 0) {
      this.setDataSource(newData);
    }
    // if(isPlainObject(data?.paging)) {
    //   const { _dataSourceName, _context } = this.props;
    //   const oldTotalCount = _context?.state?.[_dataSourceName]?.[__totalCount__]
    //   const { totalCount } = data.paging;
    //   if(typeof totalCount === 'number' && totalCount !== oldTotalCount) {
    //     this.setDataSource({
    //       [__totalCount__]: totalCount
    //     })
    //   }
    // }
  };

  makeTableSlot = (slot) => {
    if (isPlainObject(slot) && Object.keys(slot).length > 0) {
      const { _context } = this.props;
      const result = {};
      for (const key in slot) {
        const temp = slot[key];
        if (key?.includes('unsafe')) {
        } else if (typeof temp === 'function') {
          result[key] = (
            selectedRowKeys,
            selectedRowRecords,
            dataSource,
            tableInfo,
          ) => {
            return executeFunction(
              temp,
              selectedRowKeys,
              selectedRowRecords,
              dataSource,
              tableInfo,
              _context?.state,
            );
          };
        } else if (typeof temp === 'string') {
          const componentDefine = getRunTimeItem(temp);
          if (componentDefine?.component) {
            const component = getRealizeValue(componentDefine.component);
            if (component) {
              const extraProps = slot[`${key}Options`];
              result[key] = (
                selectedRowKeys,
                selectedRowRecords,
                dataSource,
                tableInfo,
              ) => {
                return React.createElement(component, {
                  selectedRowKeys,
                  selectedRowRecords,
                  dataSource,
                  tableInfo,
                  [_state]: _context?.state,
                  [_getContext]: () => {
                    return _context;
                  },
                  [_getBindFilterData]: this.getFilterParams,
                  ...extraProps,
                });
              };
            }
          }
        }
      }
      if (Object.keys(result).length > 0) {
        return result;
      }
    }
  };

  getFilterWaitComponentList = () => {
    let result;
    const { _context, _bindFilterDataSourceName } = this.props;
    if (isPlainObject(_context?._views) && _bindFilterDataSourceName) {
      for (const nodeId in _context?._views) {
        const tempView = _context?._views[nodeId];
        if (tempView?._props?._dataSourceName === _bindFilterDataSourceName) {
          const tempResult = calculateWaitComponentList(
            tempView?._props?.config,
            tempView?._props?.defaultParams,
          );
          result = tempResult?.waitComponentList;
          break;
        }
      }
    }
    return result;
  };

  getTreeConfig = () => {
    const { tree } = this.props;
    const { openKeys } = this.state;
    if (tree === true && isArrayNotEmpty(openKeys)) {
      return {
        openKeys,
        onChangeOpenKeys: (list) => {
          this.setState({
            openKeys: list,
          });
        },
      };
    }
  };

  makeRemote = (originRemote, extraConfig, originProps) => {
    const { manual, record, isInChildTable } = extraConfig || {};
    const { _context, asciiSort, treeTableAsyncRequestConfig, primaryKey } =
      originProps;
    let remote;
    if (originRemote) {
      const realUrl = getRealRequestUrl({
        requestConfig: originRemote,
        state: _context?.state,
      });
      if (realUrl) {
        const {
          params = [],
          resultProcessFunc,
          serviceType,
          mockData,
          timeout,
          contentType,
          method,
        } = originRemote;
        remote = {
          ...originRemote,
          asciiSort,
          params: undefined,
          formatParam: (param) => {
            const { currentPage, pageSize } = param || {};
            const filterParams = this.getFilterParams();
            const realParams = handleRequestParams(params, {
              urlParamsDataSource: this.getUrlParams(),
              recordDataSource: filterParams,
              state: _context?.state,
              extraParam: {
                currentPage,
                pageSize,
                record,
              },
              extraParamList: [
                {
                  currentPage,
                  pageSize,
                  record,
                },
              ],
              flexibleParams: true,
            });
            let finalResult = { ...filterParams, ...param };
            if (typeof realParams === 'function') {
              finalResult = realParams()
            } else if (Object.keys(realParams).length > 0) {
              finalResult = { ...filterParams, ...param, ...realParams };
            }
            return finalResult;
          },
          useDynamicUrl: undefined,
          dynamicUrl: undefined,
          contentType: undefined,
          url: realUrl,
        };
        if (isInChildTable) {
        } else {
          remote.instance = this.remoteInstance;
        }
        if (manual === true) {
          remote.manual = true;
        } else {
          const filterParams = this.getFilterParams();
          if (isEmpty(filterParams)) {
            const filterWaitComponentList = this.getFilterWaitComponentList();
            if (filterWaitComponentList?.length > 0) {
              remote.manual = true;
            }
          }
        }
        if (serviceType === 'http') {
          // 增加 cookie
          remote.withCredentials = true;
          // remote.requestOptions = {
          //   withCredentials:true,
          // };
          if (typeof timeout === 'number') {
            remote.requestOptions.timeout = timeout;
          }
          if (contentType === formUrlencoded) {
            remote.requestOptions.headers = {
              'content-type': contentType,
            };
          }
        } else if (serviceType === 'mokelay') {
          if (typeof timeout === 'number') {
            set(remote, 'requestOptions.timeout', timeout);
          }
        }
        if (typeof resultProcessFunc === 'function') {
          remote.formatResult = (res) => {
            let newRes = getRealResponse(res);
            try {
              const temp = resultProcessFunc(newRes);
              if (temp && temp.data && temp.success !== undefined) {
                newRes = temp.data;
              } else {
                newRes = temp;
              }
              if (isInChildTable) {
              } else {
                this.dynamicRegisterFormat(newRes);
                this.setTableInfo(newRes);
                this.sendRequestFinishEvent(newRes);
              }
            } catch (e) {
              console.error('请求结果回调执行失败', e);
            }
            return newRes;
          };
        } else if (serviceType === 'mock' && isPlainObject(mockData)) {
          remote.formatResult = () => {
            return mockData?.data;
          };
        } else {
          remote.formatResult = (res) => {
            let newRes = getRealResponse(res);
            if (newRes && newRes.data && newRes.success !== undefined) {
              newRes = newRes.data;
              if (isInChildTable) {
              } else {
                this.dynamicRegisterFormat(newRes);
                this.setTableInfo(newRes);
                this.sendRequestFinishEvent(newRes);
              }
            }
            return newRes;
          };
        }
        const asyncRealUrl = getRealRequestUrl({
          requestConfig: treeTableAsyncRequestConfig?.requestConfig,
          state: _context?.state,
        });
        if (asyncRealUrl) {
          remote.treeCache = true;
          remote.getChildrenInTree = (key, row, setLoading) => {
            setLoading?.(true);
            return makeRequest({
              needSuccessToast: false,
              buttonConfig: {
                options: {
                  requestConfig: treeTableAsyncRequestConfig.requestConfig,
                },
              },
              handleParams: (tempParam) => {
                const newParams = {
                  ...tempParam,
                };
                if (primaryKey) {
                  newParams[primaryKey] = key;
                } else {
                  newParams.id = key;
                }
                return newParams;
              },
              ...this.getCommonParams(),
            })
              .then((res) => {
                return res?.data?.tableData || [];
              })
              .finally(() => {
                setLoading(false);
              });
          };
        }
      }
    }
    return remote;
  };

  makeChildTable = (childTable) => {
    if (childTable) {
      const { _context } = this.props;
      const { remote, columns, primaryKey, buttons, dataSource } = childTable;
      if (remote?.url || isArrayNotEmpty(columns)) {
        const tableProps = {
          columns: this.handleColumns(columns),
        };
        if (isArrayNotEmpty(dataSource)) {
          tableProps.dataSource = dataSource;
        }
        return {
          renderDetail: (record, index) => {
            if (typeof dataSource === 'function') {
              tableProps.dataSource = executeFunction(
                dataSource,
                record,
                _context?.state,
                index,
              );
            }
            if (remote?.url) {
              tableProps.remote = this.makeRemote(
                remote,
                {
                  record,
                  isInChildTable: true,
                },
                {
                  _context,
                  primaryKey,
                },
              );
            }
            // 处理操作栏按钮
            if (isArrayNotEmpty(buttons)) {
              tableProps.operateColumn = {
                buttons: this.handleOperateButtons(buttons),
              };
            }
            return (
              <div key={index} style={{ padding: '16px' }}>
                <CnCardItems {...tableProps} />
              </div>
            );
          },
        };
      }
    }
  };

  makeSubTitle = (subTitle) => {
    const { _context } = this.props;
    if (typeof subTitle === 'string' && subTitle) {
      return () => {
        return subTitle;
      };
    } else if (typeof subTitle === 'function') {
      return (record) => {
        return executeFunction(subTitle, record, _context?.state);
      };
    }
  };

  makeTags = (tags) => {
    const { _context } = this.props;
    if (isArrayNotEmpty(tags)) {
      return (record) => {
        const result = [];
        tags.forEach((item) => {
          const { text, status, type } = item || {};
          const realText = calculateTextExprValue(text, {
            recordDataSource: record,
            state: _context?.state,
          });
          if (realText && status) {
            result.push({
              text: realText,
              status,
              type,
            });
          }
        });
        if (isArrayNotEmpty(result)) {
          return result;
        }
      };
    } else if (typeof tags === 'function') {
      return (record, index) => {
        return executeFunction(tags, record, _context?.state, index);
      };
    }
  };

  makeSubAction = (actions) => {
    const { _context } = this.props;
    if (isArrayNotEmpty(actions)) {
      return (record) => {
        return (
          <CnBox spacing={8} direction='row'>
            {makeButtons({
              buttons: actions.map((item) => {
                return {
                  ...item,
                  position: ButtonPosition.cnCardItemsSubAction,
                  text: true,
                  type: 'primary',
                };
              }),
              _context,
              state: _context?.state,
              urlParamsDataSource: this.getUrlParams(),
              recordDataSource: record || {},
              extraParamList: {
                recordDataSource: record || {},
              },
            })}
          </CnBox>
        );
      };
    }
  };

  render() {
    const {
      columns,
      _context,
      // 筛选栏的数据源名称
      _bindFilterDataSourceName,
      // 操作列
      buttons = [],
      _bindTable,
      showToolbar,
      showSelect,
      rowSelection,
      toolbar,
      remote: originRemote,
      __designMode,
      tableStyle,
      asciiSort,
      rowDetail,
      manual: originalManual,
      operateColumn,
      treeTableAsyncRequestConfig,
      rowProps,
      openKeys,
      columnCopyEnable,
      slot,
      useDetailValue,
      childTable,
      ...otherProps
    } = this.props;
    const isDesign = isDesignMode(this.props);
    const { tableDataSource } = this.state;
    const manual = calculateTextExprValue(originalManual, {
      recordDataSource: {},
      state: _context?.state,
    });
    const { disableDetail } = tableStyle || {};

    // 处理remote参数
    const remote = this.makeRemote(originRemote, { manual }, this.props);

    const tableProps = {
      filter: true,
      showSelect,
      rowSelection: showSelect ? this.handleRowSelection(rowSelection) : null,
      toolbar: showToolbar ? this.handleToolbar(toolbar) : null,
      requestConfig: remote,
      ...otherProps,
      ...this.handleRowDetail(rowDetail),
      onSelectChange: this.handleSelectChange.bind(
        this,
        rowSelection?.selectType,
      ),
      subTitle: this.makeSubTitle(tableStyle?.subTitle),
      tags: this.makeTags(tableStyle?.tags),
      subAction: this.makeSubAction(tableStyle?.subAction),
      disableDetail,
    };
    if (tableStyle?.columnResize === true) {
      tableProps.columnResize = {
        async: true,
      };
    }
    if (typeof tableProps.dataSource === 'function') {
      tableProps.dataSource = executeFunction(
        tableProps.dataSource,
        {},
        _context?.state,
      );
    }
    const tempSlot = this.makeTableSlot(slot);
    if (tempSlot) {
      tableProps.slot = tempSlot;
    }
    if (columnCopyEnable === true) {
      tableProps.colAttach = {
        copy: {
          primaryKey: otherProps?.primaryKey || 'id',
        },
      };
    }
    if (typeof rowProps === 'function') {
      tableProps.rowProps = (record, index) => {
        return executeFunction(rowProps, record, index, _context?.state);
      };
    }
    if (remote?.url) {
      delete tableProps.dataSource;
      if (Array.isArray(tableDataSource)) {
        tableProps.dataSource = tableDataSource;
      }
    }

    if (Array.isArray(columns) && columns.length > 0) {
      tableProps.columns = this.handleColumns(columns);
    }

    // 处理操作栏按钮
    if (Array.isArray(buttons) && buttons.length > 0) {
      tableProps.operateColumn = {
        buttons: this.handleOperateButtons(buttons),
      };
      if (typeof operateColumn?.width === 'number') {
        tableProps.operateColumn.width = operateColumn.width;
      }
    }
    if (tableProps.emptyContent) {
      if (typeof tableProps.emptyContent === 'function') {
        tableProps.emptyContent = tableProps.emptyContent(_context?.state);
      }
    }
    const treeConfig = this.getTreeConfig();
    if (isPlainObject(treeConfig)) {
      tableProps.treeConfig = treeConfig;
    }
    if (tableProps?.nodeId) {
      tableProps.storageKey = tableProps.nodeId;
    }
    if (isPlainObject(childTable)) {
      const tempChildTable = this.makeChildTable(childTable);
      if (tempChildTable) {
        tableProps.rowDetail = tempChildTable;
      }
    }

    this.handleDesignMode(tableProps, isDesign);
    // console.log(tableProps, 'table props');
    return <CnCardItems {...tableProps} />;
  }
}
export default CnTable;

export { CnTable };

CnTable.displayName = 'CnTable';
