import React from 'react';
import hotkeys from 'hotkeys-js';
import { Renderer, RendererProps } from '../factory';
import { evalExpression, filter } from '../utils/tpl';
import Button from '../components/Button';
import pick from 'lodash/pick';
import omit from 'lodash/omit';
import LionCopyItem from './Lion/components/LionCopyItem/index';
// Jay
import { Api } from '../types';
import iconMap from '../icons/font';
import { filterContents } from './Remark';
import { ClassNamesFn, themeable, ThemeProps } from '../theme';
import { autobind, createObject, deleteVariable, extendObject } from '../utils/helper';
import {
  BaseSchema,
  FeedbackDialog,
  SchemaApi,
  SchemaClassName,
  SchemaCollection,
  SchemaExpression,
  SchemaIcon,
  SchemaReload,
  SchemaTooltip,
  SchemaTpl
} from '../Schema';
import { DialogSchema, DialogSchemaBase } from './Dialog';
import { DrawerSchema, DrawerSchemaBase } from './Drawer';
import { generateIcon } from '../utils/icon';
import { BadgeSchema, withBadge } from '../components/Badge';
import { str2AsyncFunction, normalizeApi } from '../utils/api';
import { TooltipWrapper } from '../components/TooltipWrapper';
import { getHashCode } from '../utils/utils';
import { toast } from '../components/Toast';
import { tools } from '../utils/shell/tools';
import { Shell } from '../utils/shell';
import { Icon } from '../components/icons';
import { debounce, flatMap, throttle } from 'lodash';
import { confirmWithThreeButtons } from '../components/Lion/BatchOperation';
import { message, Popover } from 'antd';
import { KeyStepCommonFunction } from '../utils/keyStep';
import { IScopedContext, ScopedContext } from '../Scoped';




export interface ButtonSchema extends BaseSchema {
  /**
   * 主要用于用户行为跟踪里区分是哪个按钮
   */
  id?: string;

  /**
   * 是否为块状展示，默认为内联。
   */
  block?: boolean;

  /**
   * 禁用时的文案提示。
   */
  disabledTip?: string;

  /**
   * 按钮图标， iconfont 的类名
   */
  icon?: SchemaIcon;

  /**
   * icon 上的css 类名
   */
  iconClassName?: SchemaClassName;

  /**
   * 右侧按钮图标， iconfont 的类名
   */
  rightIcon?: SchemaIcon;

  /**
   * 右侧 icon 上的 css 类名
   */
  rightIconClassName?: SchemaClassName;
  /**
   * loading 上的css 类名
   */
  loadingClassName?: SchemaClassName;

  /**
   * 按钮文字
   */
  label?: string;

  /**
   * 按钮样式
   */
  level?:
  | 'info'
  | 'success'
  | 'warning'
  | 'danger'
  | 'link'
  | 'primary'
  | 'dark'
  | 'light';

  /**
   * @deprecated 通过 level 来配置
   */
  primary?: boolean;

  /**
   * 按钮大小
   */
  size?: 'xs' | 'sm' | 'md' | 'lg';

  tooltip?: SchemaTooltip;
  tooltipPlacement?: 'top' | 'right' | 'bottom' | 'left';

  /**
   * 指定按钮类型，支持 button、submit或者reset三种类型。
   */
  type: 'button' | 'submit' | 'reset';

  /**
   * 提示文字，配置了操作前会要求用户确认。
   */
  confirmText?: string;

  /**
   * 如果按钮在form中，配置此属性会要求用户把指定的字段通过验证后才会触发行为。
   */
  required?: Array<string>;

  /**
   * 激活状态时的样式
   */
  activeLevel?: string;

  /**
   * 激活状态时的类名
   */
  activeClassName?: string;

  /**
   * 如果按钮在弹框中，可以配置这个动作完成后是否关闭弹窗，或者指定关闭目标弹框。
   */
  close?: boolean | string;

  /**
   * 当按钮时批量操作按钮时，默认必须有勾选元素才能可点击，如果此属性配置成 false，则没有点选成员也能点击。
   */
  requireSelected?: boolean;

  /**
   * 是否将弹框中数据 merge 到父级作用域。
   */
  mergeData?: boolean;

  /**
   * 可以指定让谁来触发这个动作。
   */
  target?: string;

  /**
   * 点击后的禁止倒计时（秒）
   */
  countDown?: number;

  /**
   * 倒计时文字自定义
   */
  countDownTpl?: string;

  /**
   * 角标
   */
  badge?: BadgeSchema;

  /**
   * 键盘快捷键
   */
  hotKey?: string;
  /**
   * 是否显示loading效果
   */
  loadingOn?: string;

  /**
   * 自定义事件处理函数
   */
  onClick?: string | any;

  /**
   * 子内容
   */
  body?: SchemaCollection;

  /**
   * confirmApi
   */
  confirmApi?: SchemaApi;
  /**
   * 跳转到企微
   */
  linkApi?: SchemaApi;
}

export interface AjaxActionSchema extends ButtonSchema {
  /**
   * 指定为发送 ajax 的行为。
   */
  actionType: 'ajax';

  /**
   * 配置 ajax 发送地址
   */
  api: SchemaApi;

  feedback?: FeedbackDialog;

  reload?: SchemaReload;
  redirect?: string;
  ignoreConfirm?: boolean;
}

export interface DownloadActionSchema
  extends Omit<AjaxActionSchema, 'actionType'> {
  /**
   * 指定为下载行为
   */
  actionType: 'download';
}

export interface UrlActionSchema extends ButtonSchema {
  /**
   * 指定为打开链接
   */
  actionType: 'url';

  /**
   * 是否新窗口打开
   */
  blank?: boolean;

  /**
   * 打开的目标地址
   */
  url: string;
}

export interface DialogActionSchema extends ButtonSchema {
  /**
   * 指定为打开弹窗
   */
  actionType: 'dialog';

  /**
   * 弹框详情
   * 文档：https://baidu.gitee.io/amis/docs/components/dialog
   */
  dialog: DialogSchemaBase;

  /**
   * 是否有下一个的表达式，正常可以不用配置，如果想要刷掉某些数据可以配置这个。
   */
  nextCondition?: SchemaExpression;
  reload?: SchemaReload;
  redirect?: string;
}

export interface DrawerActionSchema extends ButtonSchema {
  /**
   * 指定为打开弹窗，抽出式弹窗
   */
  actionType: 'drawer';

  /**
   * 抽出式弹框详情
   * 文档：https://baidu.gitee.io/amis/docs/components/drawer
   */
  drawer: DrawerSchemaBase;

  /**
   * 是否有下一个的表达式，正常可以不用配置，如果想要刷掉某些数据可以配置这个。
   */
  nextCondition?: SchemaExpression;
  reload?: SchemaReload;
  redirect?: string;
}


// Aug
export interface LionChildViewActionSchema extends ButtonSchema {
  actionType: 'lion-child-view';
  lionChildView: DrawerSchemaBase;
  nextCondition?: SchemaExpression;
  reload?: SchemaReload;
  redirect?: string;
}

// Aug
export interface BatchImageViewActionSchema
  extends Omit<AjaxActionSchema, 'actionType'> {
  /**
   * 批量查看图片
   */
  actionType: 'batch-image-view';
}

export interface CopyActionSchema extends ButtonSchema {
  /**
   * 指定为复制内容行为
   */
  actionType: 'copy';

  /**
   * 复制啥内容由此配置，支持模板语法。
   */
  copy: SchemaTpl;
}

export interface LinkActionSchema extends ButtonSchema {
  /**
   * 指定为打开链接行为，跟 url 不同的时这个行为为单页模式。
   */
  actionType: 'link';

  /**
   * 跳转到哪？支持配置相对路径。
   */
  link: string;
}

export interface ReloadActionSchema extends ButtonSchema {
  /**
   * 指定为刷新目标组件。
   */
  actionType: 'reload';

  /**
   * 指定目标组件。
   */
  target?: SchemaReload;
}

export interface EmailActionSchema extends ButtonSchema {
  /**
   * 指定为打开邮箱行为
   */
  actionType: 'email';

  /**
   * 收件人邮箱
   */
  to: string;

  /**
   * 抄送邮箱
   */
  cc?: string;

  /**
   * 匿名抄送邮箱
   */
  bcc?: string;

  /**
   * 邮件主题
   */
  subject?: string;

  /**
   * 邮件正文
   */
  body?: string;
}

export interface ExportActionSchema extends ButtonSchema {
  /**
   * 指定为导出行为
   */
  actionType: "export";

  /**
   * 指定导出方式
  */

  exportType: number;
  /**
   * 导出字段
  */
  // exportFields: { name: string, label: string }[]

  // selectApi: Api

  // setApi: Api

  // deleteApi: Api

}

// Jay
export interface LabelPrintActionSchema extends
  ButtonSchema {
  actionType: 'label-design';
  defValAddApi: Api; // 新增模板
  defValDelApi: Api; // 删除模板
  defValGetApi: Api; // 获取模板
  defValEditApi: Api
  labelDataApi: Api; // 获取标签数据数组
  templateApi: Api; // 获取标签模板
  callbackApi: any; // 打印回调，发送打印时间
  numberField?: string[]; // 动态字段数组，numberField是与后端约定
  labelId?: string;
}

export interface LoginAmazonActionSchema extends ButtonSchema {

  actionType: "loginAmazon";

  /**
   * 卖家中心URL
  */

  sellerUrl: string;

  /**
   * 携带的参数
  */

  /**
 * 应用id
*/

  application_id: string;

  /**
   * 可选，指定重定向url
  */

  redirect_uri?: string;

  /**
   * 要保存到localstorage的key
  */

  schemaApi?: SchemaApi;


  tagId?: string;


  // 从按钮里面拿数据属性

  // key存到state里面，value存到localStorage

  // redirect_uri：放到saas-web

  // 回调完以后展示页面，页面请求完可以自动关闭

  // 单独刷新路由

}

export interface GroupActionSchema extends ButtonSchema {

  actionType: "action-group";

  /**
    * 存放按钮分组
    */
  actionGroups: { groupId?: string, groupName?: string, actionItems: ActionSchema[] }[]
  /**
    * 按钮分组名称
    */
  groupName: string;
  /**
   * 分组展示形式
   */
  groupType: 0 | 1;
  /**
   * 分组id
   */
  groupId?: string
  /**
  * 整体色调
  */
  groupLevel?: string

}

export interface OtherActionSchema extends ButtonSchema {
  actionType:
  | 'prev'
  | 'next'
  | 'cancel'
  | 'close'
  | 'submit'
  | 'confirm'
  | 'add'
  | 'reset'
  | 'reset-and-submit';
  [propName: string]: any;
}

export interface VanillaAction extends ButtonSchema {
  actionType?: string;
}

export const isSomeActionSchema = <T extends ActionSchema,>(actionType: string, actionSchema: ActionSchema): actionSchema is T => actionSchema.actionType == actionType

/**
 * 按钮动作渲染器。
 * 文档：https://baidu.gitee.io/amis/docs/components/action
 */
export type ActionSchema =
  | AjaxActionSchema
  | UrlActionSchema
  | LinkActionSchema
  | DialogActionSchema
  | DrawerActionSchema
  | LionChildViewActionSchema
  | BatchImageViewActionSchema
  | CopyActionSchema
  | ReloadActionSchema
  | EmailActionSchema
  | OtherActionSchema
  | VanillaAction
  | ExportActionSchema
  | LoginAmazonActionSchema
  | LabelPrintActionSchema
  | GroupActionSchema;

const ActionProps = [
  'dialog',
  'drawer',
  'url',
  'link',
  'confirmText',
  'tooltip',
  'disabledTip',
  'className',
  'asyncApi',
  'redirect',
  'size',
  'level',
  'primary',
  'feedback',
  'api',
  'blank',
  'tooltipPlacement',
  'to',
  'cc',
  'bcc',
  'subject',
  'body',
  'content',
  'required',
  'type',
  'actionType',
  'label',
  'icon',
  'rightIcon',
  'reload',
  'target',
  'close',
  'messages',
  'mergeData',
  'index',
  'copy',
  'payload',
  'requireSelected',
  'lionChildView',
  'exportType',
  'sellerUrl',
  'application_id',
  'redirect_uri',
  'schemaApi',
  // Jay 标签打印相关
  'defValAddApi',
  'defValDelApi',
  'defValGetApi',
  'defValEditApi',
  'labelDataApi',
  'templateApi',
  'primaryKey',
  'callbackApi',
  'numberField',
  'labelId',
  'linkApi',
  'deleteApi',
  'modifyApi',
  'selectApi'
];

// 构造一个假的 React 事件避免可能的报错，主要用于快捷键功能
// 来自 https://stackoverflow.com/questions/27062455/reactjs-can-i-create-my-own-syntheticevent
export const createSyntheticEvent = <T extends Element, E extends Event>(
  event: E
): React.SyntheticEvent<T, E> => {
  let isDefaultPrevented = false;
  let isPropagationStopped = false;
  const preventDefault = () => {
    isDefaultPrevented = true;
    event.preventDefault();
  };
  const stopPropagation = () => {
    isPropagationStopped = true;
    event.stopPropagation();
  };
  return {
    nativeEvent: event,
    currentTarget: event.currentTarget as EventTarget & T,
    target: event.target as EventTarget & T,
    bubbles: event.bubbles,
    cancelable: event.cancelable,
    defaultPrevented: event.defaultPrevented,
    eventPhase: event.eventPhase,
    isTrusted: event.isTrusted,
    preventDefault,
    isDefaultPrevented: () => isDefaultPrevented,
    stopPropagation,
    isPropagationStopped: () => isPropagationStopped,
    persist: () => { },
    timeStamp: event.timeStamp,
    type: event.type
  };
};

export interface ActionProps
  extends Omit<
    ButtonSchema,
    'className' | 'iconClassName' | 'rightIconClassName' | 'loadingClassName'
  >,
  ThemeProps,
  Omit<
    AjaxActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    UrlActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    LinkActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    DialogActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    DrawerActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    CopyActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    ReloadActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<
    EmailActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
    | 'body'
  >,
  Omit<
    OtherActionSchema,
    | 'type'
    | 'className'
    | 'iconClassName'
    | 'rightIconClassName'
    | 'loadingClassName'
  >,
  Omit<ExportActionSchema,
    'type' | 'className' | 'iconClassName' | 'rightIconClassName'
  >,
  Omit<LoginAmazonActionSchema,
    'type' | 'className' | 'iconClassName' | 'rightIconClassName'
  >,
  Omit<GroupActionSchema,
    'type' | 'className' | 'iconClassName' | 'rightIconClassName'
  >,
  Omit<LabelPrintActionSchema,
    'type' | 'className' | 'iconClassName' | 'rightIconClassName'
  > {
  actionType: any;
  onAction?: (
    e: React.MouseEvent<any> | void | null,
    action: ActionSchema
  ) => void;
  isCurrentUrl?: (link: string) => boolean;
  onClick?:
  | ((e: React.MouseEvent<any>, props: any) => void)
  | string
  | Function
  | null;
  componentClass: React.ReactType;
  tooltipContainer?: any;
  data?: any;
  isMenuItem?: boolean;
  active?: boolean;
}

const allowedType = ['button', 'submit', 'reset'];

interface ActionState {
  inCountDown: boolean; // 是否在倒计时
  countDownEnd: number; // 倒计时结束的精确时间
  timeLeft: number; // 倒计时剩余时间
  menuVisible?: boolean;
}

export class Action extends React.Component<ActionProps, ActionState> {
  static defaultProps = {
    type: 'button' as 'button',
    componentClass: 'button' as React.ReactType,
    tooltipPlacement: 'bottom' as 'bottom',
    activeClassName: 'is-active',
    countDownTpl: 'Action.countDown',
    countDown: 0
  };

  state: ActionState = {
    inCountDown: false,
    countDownEnd: 0,
    timeLeft: 0,
    menuVisible: false,
  };

  localStorageKey: string;

  dom: any;
  groupRef: any
  style: any
  constructor(props: ActionProps) {
    super(props);

    this.localStorageKey = 'amis-countdownend-' + (this.props.name || '');
    const countDownEnd = parseInt(
      localStorage.getItem(this.localStorageKey) || '0'
    );
    if (countDownEnd && this.props.countDown) {
      if (Date.now() < countDownEnd) {
        this.state = {
          inCountDown: true,
          countDownEnd,
          timeLeft: Math.floor((countDownEnd - Date.now()) / 1000),
        };
        this.handleCountDown();
      }
    }
  }

  // @autobind
  // async handleContextMenu(e: React.MouseEvent<any>, visible: boolean = true) {
  //   e.preventDefault()
  //   console.log(e.currentTarget, findDOMNode(this))
  //   if (e.currentTarget === findDOMNode(this)) {
  //     this.setState({
  //       menuVisible: visible
  //     })
  //   } else {
  //     this.setState({
  //       menuVisible: false
  //     })
  //   }
  // }


  @autobind
  async handleAction(e: React.MouseEvent<any>) {

    const { onAction, disabled, countDown, store, data, env } = this.props;
    // https://reactjs.org/docs/legacy-event-pooling.html
    e.persist();

    let onClick = this.props.onClick;

    let form: any;
    let _store_data: any;
    if (store) {
      form = store?.form;
      _store_data = store?.data;
    }

    if (typeof onClick === 'string') {
      onClick = str2AsyncFunction(onClick, 'event', 'props');
    }
    const result: any = onClick && (await onClick(e, this.props));

    if (
      disabled ||
      e.isDefaultPrevented() ||
      result === false ||
      !onAction ||
      this.state.inCountDown
    ) {
      return;
    }

    e.preventDefault();
    const action = pick(this.props, ActionProps) as ActionSchema;
    const actionType = action.actionType;
    // Jay
    // actionType === 'ajax'且配置了confirmText，在本地测试时不要选择移动端，直接在谷歌浏览器切换移动端模式，缩小宽度即可
    // 否则在那个手机框里（iframe）不会弹窗显示

    // ajax 会在 wrapFetcher 里记录，这里再处理就重复了，因此去掉
    // add 一般是 input-table 之类的，会触发 formItemChange，为了避免重复也去掉
    if (
      actionType !== 'ajax' &&
      actionType !== 'download' &&
      actionType !== 'add'
    ) {
      env?.tracker(
        {
          eventType: actionType || this.props.type || 'click',
          eventData: omit(action, ['type', 'actionType', 'tooltipPlacement'])
        },
        this.props
      );
    }

    // download 是一种 ajax 的简写
    if (actionType === 'download') {
      action.actionType = 'ajax';
      const api = normalizeApi((action as AjaxActionSchema).api);
      api.responseType = 'blob';
      (action as AjaxActionSchema).api = api;
    }

    onAction(e, action);

    if (countDown) {
      const countDownEnd = Date.now() + countDown * 1000;
      this.setState({
        countDownEnd: countDownEnd,
        inCountDown: true,
        timeLeft: countDown
      });

      localStorage.setItem(this.localStorageKey, String(countDownEnd));

      setTimeout(() => {
        this.handleCountDown();
      }, 1000);
    }
  }

  @autobind
  handleCountDown() {
    // setTimeout 一般会晚于 1s，经过几十次后就不准了，所以使用真实时间进行 diff
    const timeLeft = Math.floor((this.state.countDownEnd - Date.now()) / 1000);
    if (timeLeft <= 0) {
      this.setState({
        inCountDown: false,
        timeLeft: timeLeft
      });
    } else {
      this.setState({
        timeLeft: timeLeft
      });
      setTimeout(() => {
        this.handleCountDown();
      }, 1000);
    }
  }

  @autobind
  componentDidMount() {
    const { hotKey } = this.props;
    const { store, data } = this.props;
    let form: any;
    let _store_data: any;
    if (store) {
      form = store?.form;
      _store_data = store?.data;
    }



    // // 将提交的字段进行替换，以解决初始化的问题
    // Object.keys(data).map((item: any) => {
    //   if (data.hasOwnProperty('temp_' + item)) {
    //     data[item] = data['temp_' + item];
    //     deleteVariable(data, 'temp_' + item);
    //     delete data['temp_' + item];
    //     if (form) {
    //       form[item] = data[item];
    //       deleteVariable(form, 'temp_' + item);
    //       delete form['temp_' + item];
    //     }
    //     if (_store_data) {
    //       _store_data[item] = data[item];
    //       deleteVariable(_store_data, 'temp_' + item);
    //       delete _store_data['temp_' + item];
    //     }
    //   }
    // });
    if (hotKey) {
      hotkeys(hotKey, event => {
        event.preventDefault();
        const click = new MouseEvent('click', {
          bubbles: true,
          cancelable: true
        });
        this.handleAction(createSyntheticEvent(click) as any);
      });
    }
  }

  @autobind
  componentWillUnmount() {
    const { hotKey } = this.props;
    if (hotKey) {
      hotkeys.unbind(hotKey);
    }

  }



  handleIcon() {
    const { label, flowpath } = this.props
    if (label && flowpath) {
      const hashNum = getHashCode(label) % 54 || 0
      const targetIcon = iconMap[hashNum]
      return <div className="card-item-icon_amis" style={{
        backgroundColor: targetIcon.color,
      }} >
        <i className={targetIcon.icon} ></i>
      </div>
    }
    return
  }
  openWin = () => {
    const appShell: any = window['AppShell'];
    const winSchemeData = this.props.$schema?.dialog
    const winData = JSON.parse(JSON.stringify(this.props.data))
    appShell?.openNewWin(winSchemeData, sessionStorage, winData)
  }
  handleGroup = (ref: any) => {
    if (ref) {
      const width = (ref as HTMLElement).clientWidth + 'px'
      this.style = { width }

    }
  }

  render() {
    const {
      type,
      icon,
      iconClassName,
      rightIcon,
      rightIconClassName,
      loadingClassName,
      primary,
      size,
      level,
      countDownTpl,
      block,
      className,
      componentClass,
      tooltip,
      disabledTip,
      tooltipPlacement,
      actionType,
      link,
      data,
      translate: __,
      activeClassName,
      isCurrentUrl,
      isMenuItem,
      active,
      activeLevel,
      tooltipTrigger,
      tooltipContainer,
      tooltipRootClose,
      loading,
      body,
      render,
      classnames: cx,
      classPrefix: ns,
      butColor,
      flowpath,
      actionGroups,
      groupName,
      groupType,
      columnNum,
      env,
      groupLevel,
      title
    } = this.props;

    if (actionType !== 'email' && body) {
      return (
        <TooltipWrapper
          classPrefix={ns}
          classnames={cx}
          placement={tooltipPlacement}
          tooltip={tooltip}
          container={tooltipContainer}
          trigger={tooltipTrigger}
          rootClose={tooltipRootClose}
        >
          <div className={cx('Action', className)} onClick={this.handleAction}>
            {render('body', body) as JSX.Element}
          </div>
        </TooltipWrapper>
      );
    }


    let label = this.props.label;
    let disabled = this.props.disabled;
    let isActive = !!active;

    if (actionType === 'link' && !isActive && link && isCurrentUrl) {
      isActive = isCurrentUrl(link);
    }

    // 倒计时
    if (this.state.inCountDown) {
      label = filterContents(__(countDownTpl), {
        ...data,
        timeLeft: this.state.timeLeft
      }) as string;
      disabled = true;
    }

    const iconElement = icon?.includes('#') ? <Icon icon={icon} className="icon" symbol /> : this.props.actionType == 'advanced-filter' ? <Icon icon="advanced-query" className="icon" /> : generateIcon(cx, icon, 'Button-icon', iconClassName);

    const rightIconElement = generateIcon(
      cx,
      rightIcon,
      'Button-icon',
      rightIconClassName
    );

    if (actionType == 'action-group') {
      // 0: 折 1: 平铺
      if (groupType == 0) {
        return render('action-group', {
          type: 'dropdown-button',
          label: groupName,
          size: "sm",
          disabled: disabled,
          buttons: actionGroups?.map(group => {
            return {
              label: group.groupName,
              children: group.actionItems
            }
          })
        }, { columnNum, closeOnClick: true, popOverContainer: true })
      } else if (groupType == 1) {
        return render('group', { type: "button-group", buttons: flatMap(actionGroups, group => group.actionItems), disabled }, { groupLevel })
      }
    }
    return (
      <>
        {
          flowpath ?
            <div className="card-item_amis" onClick={this.handleAction
            } >
              {this.handleIcon() && this.handleIcon()}
              < div className="card-item-name_amis" >
                {!loading ? iconElement : ''}
                {label ? <>{filter(String(label), data)}</> : null}
                {rightIconElement}
              </div >
            </div > :
            // chencicsy 用于执行赋值name操作
            // 是弹窗的才能打开
            <LionCopyItem
              canOpenWin={this.props.actionType === 'dialog'}
              openWin={this.openWin}
              showItems={[{
                value: this.props.id || this.props.name,
                label: __('Alert.copyName'),
                icon: "fa fa-sticky-note-o"
              }]}
              env={this.props?.env}
            >
              <Button
                className={cx(className, {
                  [activeClassName || 'is-active']: isActive
                })}
                size={size}
                onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }}
                level={groupLevel ? groupLevel :
                  activeLevel && isActive
                    ? activeLevel
                    : level || (primary ? 'primary' : undefined)
                }
                onClick={this.handleAction}
                loadingClassName={loadingClassName as any}
                loading={loading}
                type={type && ~allowedType.indexOf(type) ? type : 'button'}
                disabled={disabled}
                componentClass={isMenuItem ? 'a' : componentClass}
                overrideClassName={isMenuItem}
                tooltip={filterContents(tooltip, data)}
                disabledTip={filterContents(disabledTip, data)}
                tooltipPlacement={tooltipPlacement}
                tooltipContainer={tooltipContainer}
                tooltipTrigger={tooltipTrigger}
                tooltipRootClose={tooltipRootClose}
                block={block}
                iconOnly={!!(icon && !label && level !== 'link')}
                butColor={butColor}
                title={title}
              >

                {!loading ? iconElement : ''}
                {label ? <span>{filter(String(label), data)}</span> : null}
                {rightIconElement}
              </Button>
            </LionCopyItem>
        } </>
    );

  }

}

export default themeable(Action);

@Renderer({
  type: 'action'
})
// @ts-ignore 类型没搞定
@withBadge
export class ActionRenderer extends React.Component<
  RendererProps &
  Omit<ActionProps, 'onAction' | 'isCurrentUrl' | 'tooltipContainer'> & {
    onAction: (
      e: React.MouseEvent<any> | void | null,
      action: object,
      data: any
    ) => void;
    btnDisabled?: boolean;
  }
> {

  static contextType = ScopedContext;
  constructor(props: RendererProps, context: IScopedContext) {
    super(props as any);
    const scoped = context;
    scoped.registerComponent(this as any);
  }

  componentWillUnmount(): void {
    const scoped = this.context as IScopedContext;
    scoped.unRegisterComponent(this as any)
  }

  @autobind
  async handleAction(e: React.MouseEvent<any> | void | null, action: any) {
    const { env, onAction, reload, api, data, ignoreConfirm, dispatchEvent, confirmApi, replace, handleSendAction, setLoading, setFieldAdd, openFullSelect, translate } = this.props;
    //标记字段表格的工具栏的新增
    setFieldAdd?.()
    // 触发渲染器事件
    const rendererEvent = await dispatchEvent(e as React.MouseEvent<any>, data);
    // 阻止原有动作执行
    if (rendererEvent?.prevented) {
      return;
    }
    if (action.type == "submit" && action.actionType == 'flow_submit_action') {
      const render = await handleSendAction?.()
      if (render !== undefined && !render) {
        return;
      }
    }
    //跳转到企微
    if (action.actionType === 'qywx-chat') {
      const { ok, data, msg } = await env.fetcher(action.linkApi, this.props.data);
      if (ok) {
        if (Shell.hasShell()) {
          Shell.openFile(2, '', data)
        } else if (tools.isComWx) {
          location.href = data;
        } else {
          location.href = data;
        }
      } else {
        return env.notify('error', msg)
      }
    }
    if (!ignoreConfirm && action.confirmText && env.confirm) {
      env
        .confirm(filter(action.confirmText, data))
        .then(async (confirmed: boolean) => {
          const confirmMsg = confirmApi && await env.fetcher(confirmApi, data);
          if (confirmMsg?.status === 10004 || confirmMsg?.status === 10001) {
            env.notify('warning', confirmMsg?.msg)
            return;
          } else if (confirmMsg?.status === 10003) {
            env?.confirm(filter(confirmMsg?.data?.showText, data)).then((confirmd: boolean) => {
              if (confirmd) {
                // env?.notify("success", "操作执行成功")
                onAction(e, action, data)
              }
              return
            })
            return
          }
          return confirmed && onAction(e, action, data)
        });
    } else {
      //需要先为全量选中和当前选中在进行confirmApi
      if (data?.selectedItems?.length && !data?.unSelectedItems?.length && openFullSelect && confirmApi) {
        onAction(e, action, data);
        return
      }
      const body = action.actionType == 'next' ? replace?.next :
        (action.actionType == 'prev' ? replace?.revious : (confirmApi ? createObject(data, {
          ...data,
          items: data.selectedItems?.concat(),
          selectedItems: data.selectedItems?.concat(),
          unSelectedItems: data.unSelectedItems?.concat(),
          rows: data.selectedItems?.concat()
        }) : data))
      try {
        setLoading?.(true)
        const confirmMsg = confirmApi && await env.fetcher(confirmApi, body).catch((ref) => {
          toast.error(ref.message);
          return { data: ref, status: 500 }
        })
        setLoading?.(false)

        if (confirmMsg?.status === 10004 || confirmMsg?.status === 10001 || confirmMsg?.status === 1) {
          env.notify('warning', confirmMsg?.msg)
          return;
        } else if (confirmMsg?.status === 500) {
          return;
        } else if (confirmMsg?.status === 10003) {
          env?.confirm(filter(confirmMsg?.data?.showText, data)).then((confirmd: boolean) => {
            if (confirmd) {
              // env?.notify("success", "操作执行成功")
              onAction(e, action, data)
            }
            return
          })
          return
        } else if (confirmMsg?.status === 10005) {
          env?.confirm(confirmMsg).then((confirmd: boolean) => {
            if (confirmd) {
              onAction(e, action, data)
            }
          })
          return
        }
      }
      catch (ref) {
        toast.error(ref.message);
        return
      }
      onAction(e, action, data);
    }
  }
  reloadTarget(target: string, data: any) {
    const scoped = this.context as IScopedContext;
    scoped.reload(target, data);
  }


  @autobind
  isCurrentAction(link: string) {
    const { env, data } = this.props;
    return env.isCurrentUrl(filter(link, data));
  }

  render() {
    const { env, disabled, btnDisabled, loading, ...rest } = this.props;


    return (
      <Action
        {...(rest as any)}
        env={env}
        disabled={disabled || btnDisabled}
        onAction={this.handleAction}
        loading={loading}
        isCurrentUrl={this.isCurrentAction}
        tooltipContainer={
          env?.getTopModalContainer || undefined
        }
      />
    );
  }
}

@Renderer({
  type: 'button'
})
export class ButtonRenderer extends ActionRenderer { }

@Renderer({
  type: 'submit'
})
export class SubmitRenderer extends ActionRenderer { }

@Renderer({
  type: 'reset'
})
export class ResetRenderer extends ActionRenderer { }
