import React from 'react';
import {
  CnDialog as UICnDialog,
  CnButton,
  CnDialogFullpage,
  formilyReact,
  CnButtonGroup,
} from '@cainiaofe/cn-ui-m';
import {
  executeFunction,
  getRealizeValue,
  isDesignMode,
  getRunTimeItem as getCommonRunTimeItem,
  isArrayNotEmpty,
  executeObjectExpr,
} from '@/common/util/util';
import {
  __dataSource__,
  __extraParam__,
  __filterValue__,
  __formValue__,
  __stateValueOfSplit__,
} from '@/common/util/expr-const';
import { _getFormValues, _state } from '@/common/util/biz-component-prop-name';
import CnForm from '@/components/cn-form';
import { ButtonPosition } from '@/type/button-position';
import {
  getButtonAction,
  getItem as getButtonItem,
  getRunTimeItem,
} from '@/common/manager/button';
import set from 'lodash/set';
import get from 'lodash/get';
import './index.scss';

const { Observer } = formilyReact || {};

class CnFormDialog extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
    };
    this.formInstance = null;
    this.formStepInstance = null;
    this.formRef = null;
  }

  getFormInstance = () => {
    return this.formInstance;
  };

  load = () => {
    this.formRef?.load?.();
  };

  reRender = () => {
    this.formRef?.reRender?.();
  };

  getForm = () => {
    const { config } = this.props;
    if (isArrayNotEmpty(config)) {
      return (
        <CnForm
          {...this.props}
          onCreateForm={(formInstance) => {
            this.formInstance = formInstance;
          }}
          dialogRef={this}
          ref={(c) => (this.formRef = c)}
        />
      );
    } else {
      return this.emptyContent();
    }
  };

  emptyContent = () => {
    // return (
    //   <div style={{
    //     padding: '20px 0 60px 0',
    //     display: 'flex',
    //     justifyContent: 'center',
    //     fontSize: '24px',
    //   }}
    //   >
    //     请在右侧表单配置面板添加表单项
    //   </div>);
    return <div />;
  };

  getExtraParam = () => {
    const { _context, _dataSourceName } = this.props;
    return {
      openDialogMode: get(
        _context?.state?.valueOf,
        `${_dataSourceName}${__stateValueOfSplit__}openDialogMode`,
      ),
    };
  };

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

  open = (data, config) => {
    const { _context, _dataSourceName } = this.props;
    const { selectedRowKeys, selectedRowRecords, buttonConfig } = config || {};
    const { options } = buttonConfig || {};
    const { openDialogMode } = options || {};
    this.selectedRowKeys = selectedRowKeys;
    this.selectedRowRecords = selectedRowRecords;
    if (data !== undefined && data !== null) {
      if (_context && _dataSourceName) {
        _context?.setState({
          [_dataSourceName]: data,
        });
      }
    }
    if (openDialogMode && _context?.state?.valueOf) {
      set(
        _context.state.valueOf,
        `${_dataSourceName}$$$openDialogMode`,
        openDialogMode,
      );
      set(
        _context.state.valueOf,
        `${_dataSourceName}${__stateValueOfSplit__}openDialogMode`,
        openDialogMode,
      );
    }
    return new Promise((resolve) => {
      setTimeout(() => {
        this.setState(
          {
            visible: true,
          },
          () => {
            // 给formInstance创建留出时间
            setTimeout(() => {
              resolve(true);
            }, 50);
          },
        );
      });
    });
  };

  getButtons = () => {
    const { buttons = [], _context } = this.props;
    if (!(buttons?.length > 0)) {
      return false;
    }
    const result = buttons.map((item, index) => {
      const {
        iconType,
        primaryKey,
        optType,
        options = {},
        children,
        type,
        hidden,
        disabled,
        ...rest
      } = item;
      const position = ButtonPosition.formDialog;
      const action = getButtonAction({
        ...item,
        position: ButtonPosition.formDialog,
      });
      const getRenderDom = getButtonItem(position, optType, 'getRenderDom');
      const componentDefine = getRunTimeItem(optType);
      const btnProps = {
        type,
      };
      const formValue = this.formInstance?.values;
      const isHidden = executeObjectExpr(
        hidden,
        {
          [__filterValue__]: formValue || {},
          [__formValue__]: formValue || {},
          [__dataSource__]: _context?.state,
          [__extraParam__]: {
            currentFormStep: this.formStepInstance?.current,
          },
        },
        formValue || {},
        _context?.state,
      );
      if (isHidden) {
        return null;
      }
      if (optType === 'submit') {
        btnProps.loading = this.formInstance?.submitting;
      }
      const isDisabled = executeObjectExpr(
        disabled,
        {
          [__filterValue__]: formValue || {},
          [__formValue__]: formValue || {},
          [__dataSource__]: _context?.state,
        },
        formValue || {},
        _context?.state,
      );
      if (isDisabled === true) {
        btnProps.disabled = true;
      }
      if (componentDefine?.component) {
        const component = getRealizeValue(componentDefine.component);
        if (component) {
          return React.createElement(component, {
            ...btnProps,
            buttonConfig: item,
            dialogRef: this,
            _context,
          });
        }
      } else if (typeof getRenderDom === 'function') {
        return executeFunction(getRenderDom, {
          _context,
          buttonConfig: item,
          state: _context?.state,
          urlParamsDataSource: this.getUrlParams(),
          recordDataSource: {
            realize: () => {
              return this?.formInstance?.values;
            },
          },
        });
      }
      if (action) {
        btnProps.onClick = action.bind(this, {
          componentProps: this.props,
          buttonConfig: item,
          open: this.open,
          close: this.close,
          dialogRef: this,
          formInstance: {
            realize: () => {
              return this?.formInstance;
            },
          },
          position: ButtonPosition.formDialog,
          state: _context?.state,
          urlParamsDataSource: this.getUrlParams(),
          recordDataSource: {
            realize: () => {
              return this?.formInstance?.values;
            },
          },
          _context,
          formStepInstance: this.formStepInstance,
          getExtraParam: this.getExtraParam,
        });
      }
      return (
        <CnButton key={index} size={'large'} fullWidth {...btnProps}>
          {children}
        </CnButton>
      );
    });
    if (Array.isArray(result) && result.length > 0) {
      const { dialogMode } = this.props;
      if (dialogMode === 'drawer') {
        return result;
      } else if (dialogMode === 'dialog') {
        return (
          <CnButtonGroup size={'large'} fullWidth>
            {result}
          </CnButtonGroup>
        );
      }
    }
  };

  close = () => {
    const { _context, _dataSourceName } = this.props;
    this.formInstance && this.formInstance.setValues({}, 'overwrite');
    this.formInstance = null;
    if (_dataSourceName) {
      const path = `${_dataSourceName}${__stateValueOfSplit__}openDialogMode`;
      if (_context) {
        set(_context.state.valueOf, path, undefined);
      }
    }
    this.setState({
      visible: false,
    });
  };

  render() {
    let { visible } = this.state;
    const { config, children, dialogMode, title, _context, ...otherProps } =
      this.props;
    const { _dataSourceName } = otherProps || {};
    const isDesign = isDesignMode(this.props);

    if (isDesign) {
      visible = true;
    }
    let Component = UICnDialog;
    if (dialogMode === 'drawer') {
      Component = CnDialogFullpage;
    }
    let realTitle = title;
    if (typeof title === 'function') {
      realTitle = executeFunction(
        title,
        get(
          _context?.state?.valueOf,
          `${_dataSourceName}${__stateValueOfSplit__}openDialogMode`,
        ),
        _context?.state,
      );
    } else {
      const componentDefine = getCommonRunTimeItem({}, title);
      if (componentDefine?.component) {
        const component = getRealizeValue(componentDefine.component);
        if (component) {
          realTitle = React.createElement(component, {
            _context,
            [_state]: _context?.state,
            [_getFormValues]: () => {
              return this?.formInstance?.values;
            },
          });
        }
      }
    }
    const componentProps = {
      className: 'cn-dialog-alc',
      ...otherProps,
      title: realTitle,
      visible,
      onClose: this.close,
      okProps: { visible: false },
      cancelProps: { visible: false },
    };
    if (isArrayNotEmpty(this.props?.buttons)) {
      componentProps.footer = (
        <Observer>
          {() => {
            return this.getButtons();
          }}
        </Observer>
      );
    } else {
      componentProps.footer = null;
    }

    return (
      <Observer>
        {() => {
          return <Component {...componentProps}>{this.getForm()}</Component>;
        }}
      </Observer>
    );
  }
}

export default CnFormDialog;

export { CnFormDialog };

CnFormDialog.displayName = 'CnFormDialog';
