import "core-js/modules/es.array.flat.js";
import "core-js/modules/es.array.unscopables.flat.js";
import "core-js/modules/es.promise.js";
import "core-js/modules/es.array.sort.js";
import "core-js/modules/es.array.iterator.js";
import "core-js/modules/web.dom-collections.iterator.js";
import React, { useContext, useEffect } from 'react';
import Descriptions from '../descriptions';
import Space from '../space';
import Form from '../form';
import ConfigProvider from '../config-provider';
import { EditOutlined, CloseOutlined, CheckOutlined } from '@wii/icons';
import toArray from 'rc-util/lib/Children/toArray';
import ProForm, { ProFormField } from '../wau-form';
import { useEditableMap, getFieldPropsOrFormItemProps, genCopyable } from '../utils';
import get from 'rc-util/lib/utils/get';
import { stringify } from 'use-json-comparison';
import ProSkeleton from '../wau-skeleton';
import useFetchData from './use-fetch-data';
import InlineErrorFormItem from '../wau-inline-form-item';
import LabelIconTip from '../wau-label-icon-tip';
import ErrorBoundary from '../wau-error-boundary';
import './style';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
import { createElement as _createElement } from "react";
/**
 * 根据 dataIndex 获取值，支持 dataIndex 为数组
 *
 * @param item
 * @param entity
 */
const getDataFromConfig = (item, entity) => {
  const {
    dataIndex
  } = item;
  if (dataIndex) {
    const data = Array.isArray(dataIndex) ? get(entity, dataIndex) : entity[dataIndex];
    if (data !== undefined || data !== null) {
      return data;
    }
  }
  return item.children;
};

/**
 * 这里会处理编辑的功能
 *
 * @param props
 */
export const FieldRender = props => {
  const {
    valueEnum,
    action,
    index,
    text,
    entity,
    mode,
    render,
    editableUtils,
    valueType,
    plain,
    dataIndex,
    request,
    renderFormItem,
    params
  } = props;
  const fieldConfig = {
    text,
    valueEnum,
    mode: mode || 'read',
    proFieldProps: {
      render: render ? () => render === null || render === void 0 ? void 0 : render(text, entity, index, action, {
        ...props,
        type: 'descriptions'
      }) : undefined
    },
    ignoreFormItem: true,
    valueType,
    request,
    params,
    plain
  };

  /** 如果是只读模式，fieldProps 的 form是空的，所以需要兜底处理 */
  if (mode === 'read' || !mode || valueType === 'option') {
    const fieldProps = getFieldPropsOrFormItemProps(props.fieldProps, undefined, {
      ...props,
      rowKey: dataIndex,
      isEditable: false
    });
    return /*#__PURE__*/_jsx(ProFormField, {
      name: dataIndex,
      ...fieldConfig,
      fieldProps: fieldProps
    });
  }
  return /*#__PURE__*/_jsx("div", {
    style: {
      marginTop: -5,
      marginBottom: -5,
      marginLeft: 0,
      marginRight: 0
    },
    children: /*#__PURE__*/_jsx(Form.Item, {
      noStyle: true,
      shouldUpdate: true,
      children: form => {
        var _editableUtils$action;
        const formItemProps = getFieldPropsOrFormItemProps(props.formItemProps, form, {
          ...props,
          rowKey: dataIndex,
          isEditable: true
        });
        const fieldProps = getFieldPropsOrFormItemProps(props.fieldProps, form, {
          ...props,
          rowKey: dataIndex,
          isEditable: true
        });
        const dom = renderFormItem ? renderFormItem === null || renderFormItem === void 0 ? void 0 : renderFormItem({
          ...props,
          type: 'descriptions'
        }, {
          isEditable: true,
          recordKey: dataIndex,
          record: form.getFieldValue([dataIndex].flat(1)),
          defaultRender: () => /*#__PURE__*/_jsx(ProFormField, {
            ...fieldConfig,
            fieldProps: fieldProps
          }),
          type: 'descriptions'
        }, form) : undefined;
        return /*#__PURE__*/_jsxs(Space, {
          children: [/*#__PURE__*/_jsx(InlineErrorFormItem, {
            name: dataIndex,
            ...formItemProps,
            style: {
              margin: 0,
              ...((formItemProps === null || formItemProps === void 0 ? void 0 : formItemProps.style) || {})
            },
            initialValue: text || (formItemProps === null || formItemProps === void 0 ? void 0 : formItemProps.initialValue),
            children: dom || /*#__PURE__*/_jsx(ProFormField, {
              ...fieldConfig,
              // @ts-ignore
              proFieldProps: {
                ...fieldConfig.proFieldProps
              },
              fieldProps: fieldProps
            })
          }), editableUtils === null || editableUtils === void 0 || (_editableUtils$action = editableUtils.actionRender) === null || _editableUtils$action === void 0 ? void 0 : _editableUtils$action.call(editableUtils, dataIndex || index, form, {
            cancelText: /*#__PURE__*/_jsx(CloseOutlined, {}),
            saveText: /*#__PURE__*/_jsx(CheckOutlined, {}),
            deleteText: false
          })]
        });
      }
    })
  });
};
const schemaToDescriptionsItem = (items, entity, action, editableUtils) => {
  var _items$map;
  const options = [];
  // 因为 Descriptions 只是个语法糖，children 是不会执行的，所以需要这里处理一下
  const children = items === null || items === void 0 || (_items$map = items.map) === null || _items$map === void 0 ? void 0 : _items$map.call(items, (item, index) => {
    var _getDataFromConfig, _restItem$label;
    if ( /*#__PURE__*/React.isValidElement(item)) {
      return item;
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const {
      valueEnum,
      render,
      renderText,
      mode,
      plain,
      dataIndex,
      request,
      params,
      editable,
      ...restItem
    } = item;
    const title = typeof restItem.title === 'function' ? restItem.title(item, 'descriptions', restItem.title) : restItem.title;
    const defaultData = (_getDataFromConfig = getDataFromConfig(item, entity)) !== null && _getDataFromConfig !== void 0 ? _getDataFromConfig : restItem.children;
    const text = renderText ? renderText(defaultData, entity, index, action) : defaultData;

    //  dataIndex 无所谓是否存在
    // 有些时候不需要 dataIndex 可以直接 render
    const valueType = typeof restItem.valueType === 'function' ? restItem.valueType(entity || {}, 'descriptions') : restItem.valueType;
    const isEditable = editableUtils === null || editableUtils === void 0 ? void 0 : editableUtils.isEditable(dataIndex || index);
    const fieldMode = mode || isEditable ? 'edit' : 'read';
    const showEditIcon = editableUtils && fieldMode === 'read' && editable !== false && (editable === null || editable === void 0 ? void 0 : editable(text, entity, index)) !== false;
    const Component = showEditIcon ? Space : React.Fragment;
    const contentDom = fieldMode === 'edit' ? text : genCopyable(text, item, text);
    const field = /*#__PURE__*/_createElement(Descriptions.Item, {
      ...restItem,
      key: ((_restItem$label = restItem.label) === null || _restItem$label === void 0 ? void 0 : _restItem$label.toString()) || index,
      label: (title || restItem.label || restItem.tooltip || restItem.tip) && /*#__PURE__*/_jsx(LabelIconTip, {
        label: title || restItem.label,
        tooltip: restItem.tooltip || restItem.tip,
        ellipsis: item.ellipsis
      })
    }, /*#__PURE__*/_jsxs(Component, {
      children: [/*#__PURE__*/_jsx(FieldRender, {
        ...item,
        dataIndex: item.dataIndex || index,
        mode: fieldMode,
        text: contentDom,
        valueType: valueType,
        entity: entity,
        index: index,
        action: action,
        editableUtils: editableUtils
      }), showEditIcon && valueType !== 'option' && /*#__PURE__*/_jsx(EditOutlined, {
        onClick: () => {
          editableUtils === null || editableUtils === void 0 ? void 0 : editableUtils.startEditable(dataIndex || index);
        }
      })]
    }));
    // 如果类型是 option 自动放到右上角
    if (valueType === 'option') {
      options.push(field);
      return null;
    }
    return field;
  }).filter(item => item);
  return {
    // 空数组传递还是会被判定为有值
    options: options !== null && options !== void 0 && options.length ? options : null,
    children
  };
};
const ProDescriptionsItem = props => {
  return /*#__PURE__*/_jsx(Descriptions.Item, {
    ...props,
    children: props.children
  });
};
const DefaultProDescriptionsDom = dom => dom.children;
const ProDescriptions = props => {
  var _props$editable;
  const {
    request,
    columns,
    params = {},
    dataSource,
    onDataSourceChange,
    formProps,
    editable,
    loading,
    onLoadingChange,
    actionRef,
    onRequestError,
    ...rest
  } = props;
  const context = useContext(ConfigProvider.ConfigContext);
  const action = useFetchData(async () => {
    const data = request ? await request(params) : {
      data: {}
    };
    return data;
  }, {
    onRequestError,
    effects: [stringify(params)],
    manual: !request,
    dataSource,
    loading,
    onLoadingChange,
    onDataSourceChange
  });

  /*
   * 可编辑行的相关配置
   */
  const editableUtils = useEditableMap({
    ...props.editable,
    childrenColumnName: undefined,
    dataSource: action.dataSource,
    setDataSource: action.setDataSource
  });

  /** 支持 reload 的功能 */
  useEffect(() => {
    if (actionRef) {
      actionRef.current = {
        reload: action.reload,
        ...editableUtils
      };
    }
  }, [action, actionRef, editableUtils]);

  // loading 时展示
  // loading =  undefined 但是 request 存在时也应该展示
  if (action.loading || action.loading === undefined && request) {
    return /*#__PURE__*/_jsx(ProSkeleton, {
      type: "descriptions",
      list: false,
      pageHeader: false
    });
  }
  const getColumns = () => {
    // 因为 Descriptions 只是个语法糖，children 是不会执行的，所以需要这里处理一下
    const childrenColumns = toArray(props.children).map(item => {
      const {
        valueEnum,
        valueType,
        dataIndex,
        ellipsis,
        copyable,
        request: itemRequest
      } = item.props;
      if (!valueType && !valueEnum && !dataIndex && !itemRequest && !ellipsis && !copyable) {
        return item;
      }
      return {
        ...item.props,
        entity: dataSource
      };
    });
    return [...(columns || []), ...childrenColumns].filter(item => {
      if (['index', 'indexBorder'].includes(item === null || item === void 0 ? void 0 : item.valueType)) {
        return false;
      }
      return !(item !== null && item !== void 0 && item.hideInDescriptions);
    }).sort((a, b) => {
      if (b.order || a.order) {
        return (b.order || 0) - (a.order || 0);
      }
      return (b.index || 0) - (a.index || 0);
    });
  };
  const {
    options,
    children
  } = schemaToDescriptionsItem(getColumns(), action.dataSource || {}, (actionRef === null || actionRef === void 0 ? void 0 : actionRef.current) || action, editable ? editableUtils : undefined);

  /** 如果不是可编辑模式，没必要注入 ProForm */
  const FormComponent = editable ? ProForm : DefaultProDescriptionsDom;

  /** 即使组件返回null了, 在传递的过程中还是会被Description检测到为有值 */
  let title = null;
  if (rest.title || rest.tooltip || rest.tip) {
    title = /*#__PURE__*/_jsx(LabelIconTip, {
      label: rest.title,
      tooltip: rest.tooltip || rest.tip
    });
  }
  const className = context.getPrefixCls('pro-descriptions');
  return /*#__PURE__*/_jsx(ErrorBoundary, {
    children: /*#__PURE__*/_jsx(FormComponent, {
      form: (_props$editable = props.editable) === null || _props$editable === void 0 ? void 0 : _props$editable.form,
      component: false,
      submitter: false,
      ...formProps,
      onFinish: undefined,
      children: /*#__PURE__*/_jsx(Descriptions, {
        className: className,
        ...rest,
        extra: rest.extra ? /*#__PURE__*/_jsxs(Space, {
          children: [options, rest.extra]
        }) : options,
        title: title,
        children: children
      })
    }, "form")
  });
};
ProDescriptions.Item = ProDescriptionsItem;
export default ProDescriptions;