import {
  calculateRequestExecute,
  calculateTextExprValue,
  condition,
  executeObjectExpr,
  getArrayTableCurrentIndex,
  getArrayTableCurrentRowByField,
  getRealRequestUrl,
  handleDesignMokelayUrl,
  handleFormUrlencodedContentType,
  handleRequestExtraConfig,
  handleSelectRequestConfig,
  isValueObjectExpr,
  setAdvancedConfigToProps,
} from '../../util/util';
import {
  CnAsyncSelect,
  componentMap as formComponentMap,
  CnTooltip,
  formilyReact,
} from '@cainiaofe/cn-ui';
import { DisplayPosition } from '../position/display-position';
import { getRealResponse, handleRequestParams } from '../../util/request';
import { getJSExpressionPrototype } from '../common-style';
import isPlainObject from 'lodash/isPlainObject';
import cloneDeep from 'lodash/cloneDeep';
import {
  __arrayTableCurrentRow__,
  __dataSource__,
  __extraParam__,
  __filterValue__,
  __formValue__,
  __tableCurrentRow__,
  componentRefSplit,
  currentPageLabel,
  pageSizeLabel,
} from '@/common/util/expr-const';
import {
  getArrayTableCurrentRowFieldSnippet,
  getExprSetterSnippet,
  getRequestExecuteSetter,
  getRequestWhenFocusSetterSnippet,
  getStaticDataSourceSnippet,
} from '@/common/manager/setter-snippet';
import {
  __advancedConfig__,
  dataOriginRequest,
  formComponentRefStorage,
  formUrlencoded,
} from '@/common/util/const';
import { ParamSelectSetter } from '@/common/setter/param-select-setter';
import qs from 'query-string';
import { forwardRef, useRef } from 'react';
import {
  getBizExtendPrototype,
  handleBizExtendComponentProps,
} from '@/common/manager/plugin';

const { useField } = formilyReact || {};

function visibleRun(extraProps, visible, type, run) {
  const {
    requestConfig,
    state,
    recordDataSource,
    arrayTableCurrentRow,
    getFormInstance,
  } = extraProps || {};
  const realFormValue = getFormInstance?.()?.values || recordDataSource;
  const execute = calculateRequestExecute(
    requestConfig,
    {
      [__formValue__]: realFormValue,
      [__filterValue__]: realFormValue,
      [__arrayTableCurrentRow__]: arrayTableCurrentRow || {},
      [__dataSource__]: state,
    },
    realFormValue || {},
    state,
    { [__arrayTableCurrentRow__]: arrayTableCurrentRow || {} },
  );
  if (visible && execute !== false) {
    run?.();
  }
}

function tempFormBeforeHandler(
  props,
  {
    isDesign,
    urlParamsDataSource,
    recordDataSource,
    state,
    componentRequestFinish,
    filterItemConfig,
    isInForm,
    formInstance,
    _context,
    getFormInstance,
    formItemConfig,
    formProps,
    parentPosition,
  },
) {
  const { _dataSourceName } = formProps || {};
  const realName = filterItemConfig?.name || formItemConfig?.name;
  const newProps = cloneDeep(props);
  const {
    dataOrigin,
    requestConfig,
    dataSource,
    multipleExtraProps,
    manual,
    requestWhenFocus,
  } = newProps || {};
  const { serviceType, mockData, method } = requestConfig || {};
  const { initRequestConfig, hideMaxTag, maxTagCount } =
    multipleExtraProps || {};
  if (dataOrigin === 'static') {
    if (typeof dataSource === 'function') {
      if ([DisplayPosition.cnArraySubAreaCard].includes(parentPosition)) {
        newProps.getRequestParams = () => {
          return {
            state: _context?.state,
            recordDataSource,
          };
        };
      } else {
        try {
          const temp = dataSource(state, {});
          if (Array.isArray(temp)) {
            newProps.dataSource = temp;
          }
        } catch (e) {
          const tempTitle = formItemConfig?.label || formItemConfig?.name;
          console.error(`${tempTitle} 的数据源表达式执行错误`);
        }
      }
    } else if (isValueObjectExpr(dataSource)) {
      const tempDs = calculateTextExprValue(dataSource, { state });
      if (Array.isArray(tempDs)) {
        newProps.dataSource = tempDs;
      } else {
        newProps.dataSource = [];
      }
    }
    if (!Array.isArray(newProps.dataSource)) {
      if ([DisplayPosition.cnArraySubAreaCard].includes(parentPosition)) {
      } else {
        newProps.dataSource = [];
      }
    }
    if (newProps?.mode === 'multiple' || newProps?.mode === 'tag') {
      if (hideMaxTag === true) {
        newProps.maxTagPlaceholder = () => {
          return null;
        };
      }
    }
    if (typeof maxTagCount === 'number') {
      newProps.maxTagCount = maxTagCount;
      newProps.tagInline = false;
    }
    delete newProps.requestConfig;
  } else {
    if (isInForm) {
      newProps.getRequestParams = () => {
        return {
          state: _context?.state,
          recordDataSource,
          getFormInstance,
        };
      };
    } else {
      const realUrl = getRealRequestUrl({
        requestConfig: newProps?.requestConfig,
        state,
        extraParam: {},
      });
      if (realUrl) {
        newProps.requestConfig.url = realUrl;
        delete newProps.requestConfig.dynamicUrl;
      }
      const execute = calculateRequestExecute(
        requestConfig,
        {
          [__dataSource__]: state,
        },
        recordDataSource || {},
        state,
      );
      if (execute === false) {
        if (newProps?.requestConfig) {
          newProps.requestConfig.manual = true;
        }
      }
      if (requestWhenFocus === false) {
      } else {
        newProps.onVisibleChange = visibleRun.bind(this, {
          requestConfig,
          state,
          recordDataSource,
        });
      }
    }
    if (dataOrigin === 'request') {
      delete newProps.dataSource;
    }
    if (newProps?.requestConfig?.serviceType === 'mokelay') {
      newProps.requestConfig.method = 'post';
      if (isDesign && newProps?.requestConfig?.url) {
        newProps.requestConfig.url = handleDesignMokelayUrl(
          newProps.requestConfig?.url,
        );
      }
    } else if (newProps?.requestConfig) {
      newProps.requestConfig.withCredentials = true;
    }

    if (
      Array.isArray(newProps?.requestConfig?.params) &&
      newProps?.requestConfig?.params.length > 0
    ) {
      const { params } = newProps.requestConfig;
      newProps.requestConfig.searchFormat = (
        originalParam,
        extraRequestParams,
      ) => {
        let realRecord = recordDataSource;
        let realState = state;
        if (isInForm) {
          if (typeof getFormInstance === 'function') {
            realRecord = getFormInstance()?.values;
          } else if (formInstance?.values) {
            realRecord = formInstance.values;
          }
          if (_context?.state) {
            realState = _context.state;
          }
        }
        const paramConfig = {
          urlParamsDataSource,
          recordDataSource: realRecord,
          state: realState,
          ...extraRequestParams,
          extraParamList: [{}],
        };
        if (extraRequestParams?.__arrayTableCurrentRow__) {
          paramConfig.getExtraParam = () => {
            return {
              [__arrayTableCurrentRow__]:
                extraRequestParams?.__arrayTableCurrentRow__,
            };
          };
          paramConfig.extraParamList = [
            {
              [__arrayTableCurrentRow__]:
                extraRequestParams?.__arrayTableCurrentRow__,
            },
          ];
        }
        const realParams = handleRequestParams(params, paramConfig);
        const tempResult = { ...realParams, ...originalParam };
        if (
          serviceType === 'http' &&
          method === 'post' &&
          requestConfig?.contentType === formUrlencoded
        ) {
          return qs.stringify(tempResult);
        }
        return tempResult;
      };
      delete newProps.requestConfig.params;
    }

    // if(isInForm === true) {
    //   newProps.getRequestParams = ()=>{
    //     let temp1 = recordDataSource;
    //     let temp2 = state;
    //     if(formInstance?.values) {
    //       temp1 = formInstance.values;
    //     }
    //     if(_context?.state) {
    //       temp2 = _context?.state;
    //     }
    //     return {
    //       urlParamsDataSource,
    //       recordDataSource: temp1,
    //       state: temp2,
    //     }
    //   }
    // }else{
    //   if (Array.isArray(newProps?.requestConfig?.params) && newProps?.requestConfig?.params.length > 0) {
    //     const realParams = handleRequestParams(newProps?.requestConfig?.params, {
    //       urlParamsDataSource,
    //       recordDataSource,
    //       state,
    //     });
    //     if (realParams) {
    //       if (newProps?.requestConfig?.method === 'post') {
    //         newProps.requestConfig.data = realParams;
    //         delete newProps.requestConfig.params;
    //       } else {
    //         newProps.requestConfig.params = realParams;
    //       }
    //     }
    //   }
    // }
    if (typeof newProps?.requestConfig?.resultProcessFunc === 'function') {
      newProps.requestConfig.formatResult = (res) => {
        let newRes = getRealResponse(res);
        try {
          newRes = newProps?.requestConfig?.resultProcessFunc(newRes);
        } catch (e) {
          console.error('请求结果回调执行失败', e);
        }

        if (Array.isArray(newRes?.data)) {
          newRes = newRes.data;
        } else if (Array.isArray(newRes?.data?.dataSource)) {
          newRes = newRes?.data?.dataSource;
        }
        componentRequestFinish?.({ name: realName, dataSource: newRes });
        return newRes;
      };
    } else if (serviceType === 'mock' && isPlainObject(mockData)) {
      newProps.requestConfig.formatResult = () => {
        componentRequestFinish?.({
          name: realName,
          dataSource: mockData?.data,
        });
        return mockData?.data;
      };
    } else if (newProps?.requestConfig) {
      newProps.requestConfig.formatResult = (res) => {
        let newRes = getRealResponse(res);
        if (Array.isArray(newRes?.data)) {
          newRes = newRes.data;
        } else if (Array.isArray(newRes?.data?.dataSource)) {
          newRes = newRes?.data?.dataSource;
        }
        componentRequestFinish?.({ name: realName, dataSource: newRes });
        return newRes;
      };
    }
    if (newProps?.searchRemote) {
      newProps.filterLocal = false;
      if (newProps?.searchKey && newProps?.requestConfig) {
        newProps.requestConfig.searchKey = newProps.searchKey;
      }
    }
    if (newProps?.requestConfig) {
      newProps.requestConfig.throttleWait = 800;
    }

    if (newProps?.mode === 'multiple' || newProps?.mode === 'tag') {
      if (hideMaxTag === true) {
        newProps.maxTagPlaceholder = () => {
          return null;
        };
      }
      if (typeof maxTagCount === 'number') {
        newProps.maxTagCount = maxTagCount;
        newProps.tagInline = false;
      }
      if (initRequestConfig) {
        const realInitUrl = getRealRequestUrl({
          requestConfig: initRequestConfig,
          state,
        });
        if (realInitUrl) {
          initRequestConfig.url = realInitUrl;
        }
        const tempProps = {
          dataOrigin: 'request',
          requestConfig: initRequestConfig,
        };
        handleSelectRequestConfig({
          componentProps: tempProps,
          isDesign,
          urlParamsDataSource,
          recordDataSource,
          state,
        });
        if (tempProps?.requestConfig) {
          newProps.initRequestConfig = {
            ...tempProps.requestConfig,
          };
          if (multipleExtraProps?.searchKey) {
            newProps.initRequestConfig.searchKey = multipleExtraProps.searchKey;
          }
        }
      }
    } else {
      delete newProps?.initRequestConfig;
    }
    if (manual === true && newProps?.requestConfig) {
      newProps.requestConfig.manual = true;
    }
  }

  delete newProps.searchRemote;
  delete newProps.searchKey;
  delete newProps.manual;
  newProps.showSearch = true;

  newProps.autoWidth = false;
  if (newProps.mode === 'single') {
    delete newProps.hasSelectAll;
  }

  delete newProps.multipleExtraProps;
  handleBizExtendComponentProps(newProps, 'CnAsyncSelect');
  setAdvancedConfigToProps(newProps);
  handleFormUrlencodedContentType(newProps?.requestConfig);
  handleRequestExtraConfig(newProps?.requestConfig, state);
  newProps._dataSourceName = _dataSourceName;

  return newProps;
}

export function getSelectParamSelectSetter(config) {
  const { position } = config || {};
  let paramSelectSetter = {
    componentName: 'ParamSelectSetter',
    props: {
      ParamSelectSetterComponent: ParamSelectSetter,
      dataKey: 'config',
      labelKey: 'label',
      valueKey: 'name',
      groupName: '参数列表',
    },
    title: '选择参数',
  };
  if (position === DisplayPosition.cnArrayTable) {
    paramSelectSetter = {
      componentName: 'ParamSelectSetter',
      props: {
        dataKey: 'arrayTable',
        labelKey: 'label',
        valueKey: 'name',
        groupName: '表格当前行数据',
        groupExprName: __tableCurrentRow__,
      },
      title: '选择参数',
    };
  } else if (position === DisplayPosition.cnArraySubAreaCard) {
    paramSelectSetter = {
      componentName: 'ParamSelectSetter',
      props: {
        ParamSelectSetterComponent: ParamSelectSetter,
        configList: [
          {
            dataKey: 'config',
            labelKey: 'label',
            valueKey: 'name',
            groupName: '当前表单',
          },
          getArrayTableCurrentRowFieldSnippet(),
          {
            groupName: '其他数据',
            groupExprName: __dataSource__,
            needSecondParam: true,
          },
        ],
      },
      title: '选择参数',
    };
  }
  return paramSelectSetter;
}

const Select = {
  position: [
    DisplayPosition.form,
    DisplayPosition.formDialog,
    DisplayPosition.filter,
    DisplayPosition.cnArrayTable,
    DisplayPosition.cnArraySubAreaCard,
  ],
  thumbUrl:
    'https://img.alicdn.com/imgextra/i4/O1CN01adXHIL1kRURqxjeyg_!!6000000004680-2-tps-240-144.png',
  title: '下拉选择',
  componentName: 'Select',
  component: CnAsyncSelect,
  tempFormBeforeHandler,
  formComponent: forwardRef((props, ref) => {
    let realRef;
    let tempRef;
    const field = useField?.();
    const fieldEntire = field?.path?.entire;
    const { _dataSourceName } = props || {};
    if (typeof ref === 'function') {
      tempRef = (target) => {
        ref?.(target);
        if (fieldEntire && _dataSourceName && target) {
          formComponentRefStorage[
            `${_dataSourceName}${componentRefSplit}${fieldEntire}`
          ] = {
            current: target,
          };
        }
      };
    } else {
      realRef = useRef(null);
    }
    const extraProps = {
      getRequestParams: undefined,
      requestWhenFocus: undefined,
    };
    if (
      props?.dataOrigin === dataOriginRequest &&
      isPlainObject(props.requestConfig)
    ) {
      const { getRequestParams } = props;
      let _params;
      const extraParam = {};
      if (typeof getRequestParams === 'function') {
        _params = getRequestParams();
      }
      extraParam[__arrayTableCurrentRow__] =
        getArrayTableCurrentRowByField(useField?.()) || {};

      if (
        typeof props.requestConfig.dynamicUrl === 'function' &&
        props.requestConfig.useDynamicUrl === true
      ) {
        const realUrl = getRealRequestUrl({
          requestConfig: props.requestConfig,
          ..._params,
          extraParam,
        });
        if (realUrl && typeof realUrl === 'string') {
          props.requestConfig.url = realUrl;
        }
      }

      const { getFormInstance } = _params || {};
      const execute = calculateRequestExecute(
        props?.requestConfig,
        {
          [__formValue__]: _params?.recordDataSource,
          [__filterValue__]: _params?.recordDataSource,
          [__dataSource__]: _params?.state,
          ...extraParam,
        },
        _params?.recordDataSource || {},
        _params?.state,
        extraParam || {},
      );
      if (execute === false) {
        props.requestConfig.manual = true;
      }

      if (props?.requestWhenFocus === false) {
      } else {
        extraProps.onVisibleChange = visibleRun.bind(this, {
          requestConfig: props?.requestConfig,
          state: _params?.state,
          recordDataSource: _params?.recordDataSource,
          arrayTableCurrentRow: extraParam[__arrayTableCurrentRow__],
          getFormInstance,
        });
      }
    }

    if (typeof props?.requestConfig?.searchFormat === 'function') {
      const currentRow = getArrayTableCurrentRowByField(useField?.());
      if (isPlainObject(currentRow)) {
        const oldSearchFormat = props.requestConfig.searchFormat;
        props.requestConfig.searchFormat = (originalParam) => {
          const copyCurrentRow = { ...currentRow };
          return oldSearchFormat(originalParam, {
            tableCurrentRow: copyCurrentRow,
            __arrayTableCurrentRow__: copyCurrentRow,
          });
        };
      }
    }

    // const params = props?.requestConfig?.params;
    // if (Array.isArray(params) && params?.length > 0) {
    //   const field = useField?.();
    //   let _params = {};
    //   const { getRequestParams } = props;
    //   if(typeof getRequestParams === 'function') {
    //     _params = getRequestParams();
    //   }
    //   if(typeof field?.index === 'number'){
    //     const temp = field.query('..').value();
    //     const currentRow = temp?.[field.index];
    //     if(isPlainObject(currentRow)) {
    //       _params.tableCurrentRow = currentRow;
    //     }
    //   }
    //   const realParams = handleRequestParams(params, { ..._params });
    //   if (realParams) {
    //     if (props?.requestConfig?.method === 'post') {
    //       props.requestConfig.data = realParams;
    //       delete props.requestConfig.params;
    //     } else {
    //       props.requestConfig.params = realParams;
    //     }
    //   }else {
    //     delete props.requestConfig.params;
    //   }
    // }
    if (_dataSourceName && fieldEntire && realRef) {
      formComponentRefStorage[
        `${_dataSourceName}${componentRefSplit}${fieldEntire}`
      ] = realRef;
    }
    if (typeof props?.dataSource === 'function') {
      extraProps.dataSource = [];
      try {
        let _params;
        const { getRequestParams } = props;
        if (typeof getRequestParams === 'function') {
          _params = getRequestParams();
        }
        const record = getArrayTableCurrentRowByField(field) || {};
        const index = getArrayTableCurrentIndex(field);
        const temp = props.dataSource(_params?.state || {}, {
          record,
          index,
        });
        if (Array.isArray(temp)) {
          extraProps.dataSource = temp;
        }
      } catch (e) {}
    }
    return (
      <formComponentMap.CnAsyncSelect
        {...props}
        {...extraProps}
        ref={tempRef || realRef}
      />
    );
  }),
  getDefaultProps: () => {
    return {
      dataOrigin: 'request',
      mode: 'single',
    };
  },
  getFormItemDefaultProps: () => {
    return {
      placeholder: '请选择',
    };
  },
  // select的prototype列表
  getPrototypeList: (position) => {
    const extraServiceProps = {};
    let jsExpressionPrototype = getJSExpressionPrototype({
      type: 'formRequest',
    });
    let executeProps = {
      initialCode: `(formValues, state) => {
  return formValues.xxxx === "xxxx";
}`,
      tip: `当前函数需要返回 true/false。
formValues：当前筛选栏/表单的数据。
state：全部的数据，在左侧列表中选择使用。
`,
    };
    if (DisplayPosition.cnArrayTable === position) {
      extraServiceProps.dynamicUrlTemplate = `function(state, { ${__arrayTableCurrentRow__} }) {
  // __arrayTableCurrentRow__: 可编辑表格当前行的数据。
  return '/xxx';
}`;
      executeProps = {
        initialCode: `(formValues, state, { ${__arrayTableCurrentRow__} }) => {
  return formValues.xxxx === "xxxx";
}`,
        tip: `当前函数需要返回 true/false。
formValues：当前筛选栏/表单的数据。
state：全部的数据，在左侧列表中选择使用。
__arrayTableCurrentRow__：可编辑表格当前行的数据。
`,
      };
      jsExpressionPrototype = getJSExpressionPrototype({
        type: 'arrayTableCurrentRow',
      });
    }
    const paramSelectSetter = getSelectParamSelectSetter({ position });
    let extraConfigSetter;
    const requestExecuteSetter = getRequestExecuteSetter({
      exprSetter: getExprSetterSnippet({
        position,
      }),
    });
    let staticSetter = getStaticDataSourceSnippet();
    if (DisplayPosition.cnArraySubAreaCard === position) {
      staticSetter = getStaticDataSourceSnippet({
        jsExpressionSetter: getJSExpressionPrototype({
          type: 'selectInArrayCard',
        }),
      });
    }
    if (requestExecuteSetter) {
      extraConfigSetter = [requestExecuteSetter];
      extraConfigSetter.push({
        name: 'headers',
        title: '设置请求头(headers)',
        setter: {
          componentName: 'MixedSetter',
          props: {
            setters: [
              getJSExpressionPrototype({ type: 'headers' }),
              {
                componentName: 'JsonSetter',
                title: '编辑JSON',
              },
            ],
          },
        },
      });
    }
    return [
      // {
      //   title: '下拉选择配置',
      //   type:'group',
      //   display: 'accordion',
      //   collapsed:true,
      //   // hidden: hidden('Select'),
      //   condition(prop){
      //     return condition(prop,'Select','componentName')
      //   },
      // },
      {
        name: 'mode',
        title: '选择模式',
        display: 'inline',
        setter: {
          componentName: 'RadioGroupSetter',
          props: {
            options: [
              {
                title: '单选',
                value: 'single',
              },
              {
                title: '多选',
                value: 'multiple',
              },
              {
                title: '既可选择也可输入',
                value: 'tag',
              },
            ],
          },
        },
      },
      {
        name: 'dataOrigin',
        title: '数据来源',
        display: 'inline',
        setter: {
          componentName: 'RadioGroupSetter',
          props: {
            options: [
              { title: '远程请求', value: 'request' },
              { title: '静态数据', value: 'static' },
            ],
          },
        },
      },
      {
        name: 'requestConfig',
        title: '查询服务',
        display: 'inline',
        setter: {
          componentName: 'ServiceChoiceSetter',
          props: {
            dialogClassName: 'l2-cn-select-sc-dialog',
            mockDataTemplate: {
              success: true,
              data: [
                {
                  label: '选项一',
                  value: 'first',
                },
                {
                  label: '选项二',
                  value: 'second',
                },
              ],
            },
            paramTitleDom: <div className=''>请求参数配置：</div>,
            responseDom: (
              <div style={{ paddingTop: '10px' }}>
                请求返回结果的数据结构：
                <a
                  target={'_blank'}
                  href='https://yuque.antfin.com/cn-framework-committee/cn-ui-data-structure/cn-async-select#iEuF0'
                  rel='noreferrer'
                >
                  接口文档
                </a>{' '}
                <CnTooltip v2 align={'t'} trigger={<a>接口预览</a>}>
                  <div style={{ width: '200px', height: '260px' }}>
                    <img
                      style={{ width: '100%' }}
                      src='https://img.alicdn.com/imgextra/i1/O1CN01W5SNFR25Fg4QyRC53_!!6000000007497-0-tps-456-570.jpg'
                    />
                  </div>
                </CnTooltip>
              </div>
            ),
            buttonText: '选择请求API',
            params: {
              env: 'pre',
              pageSize: 999,
              // serviceType: 'HSF',
            },
            extraConfigSetter,
            paramSetter: {
              componentName: 'MixedSetter',
              props: {
                setters: [
                  paramSelectSetter,
                  {
                    componentName: 'StringSetter',
                    title: '字符串',
                  },
                  jsExpressionPrototype,
                ],
              },
            },
            resultProcessFuncTemplate: `function(res) {
  // 需要返回的如下的数据结构
  // return {
  //   success: true,
  //   data: [
  //     {
  //        label:"xx",
  //        value:"xx",
  //     }
  //   ]
  // }
 return res;
}`,
            // paramSetter:{
            //   componentName: 'ParamSelectSetter',
            //   props:{
            //     dataKey: 'config',
            //     labelKey: 'label',
            //     valueKey: 'name',
            //     groupName: '参数列表',
            //   },
            //   title:'选择参数',
            // },
            executeProps,
            ...extraServiceProps,
          },
        },
        // hidden:hidden('Select'),
        condition(prop) {
          return (
            condition(prop, 'Select', 'componentName') &&
            prop?.parent?.getPropValue?.('dataOrigin') !== 'static'
          );
        },
      },
      {
        name: 'dataSource',
        title: '编辑静态数据',
        display: 'plain',
        tip: '编辑静态展示数据',
        // initialValue: [],
        className: 'cn-datasource-relative-setter',
        setter: staticSetter,
        // setter: {
        //   componentName: 'ArraySetter',
        //   props: {
        //     mode: 'list',
        //     itemSetter: {
        //       componentName: 'ObjectSetter',
        //       // initialValue: {
        //       //   "type": "JSFunction",
        //       //   "value": "() => {return {primaryKey: String(Math.floor(Math.random() * 10000)),children: \"Title\",optType:\"link\"               };}"
        //       // },
        //       initialValue: {
        //         label: '名称',
        //         value: 'jack',
        //       },
        //       props: {
        //         config: {
        //           items: [
        //             {
        //               name: 'label',
        //               display: 'inline',
        //               title: '标签',
        //               isRequired: true,
        //               setter: 'StringSetter',
        //             },
        //             {
        //               name: 'value',
        //               display: 'inline',
        //               title: '值',
        //               isRequired: true,
        //               setter: {
        //                 componentName: 'MixedSetter',
        //                 props: {
        //                   setters: [
        //                     {
        //                       componentName:'StringSetter',
        //                       title:'字符串',
        //                     },
        //                     {
        //                       componentName:'NumberSetter',
        //                       title:'数字',
        //                     },
        //                     {
        //                       componentName:'BoolSetter',
        //                       title:'布尔（true/false）',
        //                     },
        //                   ],
        //                 },
        //               }
        //             },
        //           ],
        //         },
        //       },
        //     },
        //   },
        // },
        // supportVariable: true,
        // hidden:hidden('Select'),
        condition(prop) {
          return (
            condition(prop, 'Select', 'componentName') &&
            prop?.parent?.getPropValue?.('dataOrigin') === 'static'
          );
        },
      },
      {
        name: 'manual',
        title: '初始不请求',
        display: 'inline',
        defaultValue: false,
        setter: {
          componentName: 'RadioGroupSetter',
          props: {
            options: [
              { title: '是', value: true },
              { title: '否', value: false },
            ],
          },
        },
      },
      getRequestWhenFocusSetterSnippet(),
      {
        name: 'searchRemote',
        title: '当新输入时 重新发请求',
        display: 'inline',
        tip: '开启时，每次输入都会重新发请求获取数据',
        setter: {
          componentName: 'RadioGroupSetter',
          props: {
            options: [
              { title: '是', value: true },
              { title: '否', value: false },
              { title: '不设置' },
            ],
          },
        },
      },
      {
        name: 'searchKey',
        title: '远程搜索时的key',
        display: 'inline',
        setter: {
          componentName: 'StringSetter',
          props: {},
        },
        condition(prop) {
          return (
            condition(prop, 'Select', 'componentName') &&
            prop?.parent?.getPropValue?.('searchRemote') === true
          );
        },
      },
      {
        name: 'useDetailValue',
        title: '使用详细数据 ',
        display: 'inline',
        setter: {
          componentName: 'RadioGroupSetter',
          props: {
            options: [
              { title: '是', value: true },
              { title: '否', value: false },
              { title: '不设置' },
            ],
          },
        },
      },
      {
        name: 'hasSelectAll',
        title: '支持全选',
        display: 'inline',
        setter: {
          componentName: 'RadioGroupSetter',
          props: {
            options: [
              { title: '是', value: true },
              { title: '否', value: false },
              { title: '不设置' },
            ],
          },
        },
        condition(prop) {
          return (
            condition(prop, 'Select', 'componentName') &&
            prop?.parent?.getPropValue?.('mode') === 'multiple'
          );
        },
      },
      {
        title: '多选时的额外配置项',
        name: 'multipleExtraProps',
        display: 'accordion',
        setter: {
          componentName: 'ObjectSetter',
          props: {
            config: {
              items: [
                {
                  name: 'initRequestConfig',
                  title: '多选时，初始化回显数据的API',
                  display: 'inline',
                  setter: {
                    componentName: 'ServiceChoiceSetter',
                    props: {
                      paramTitleDom: <div className=''>请求参数配置：</div>,
                      responseDom: (
                        <div style={{ paddingTop: '10px' }}>
                          请求返回结果的数据结构：
                          <a
                            target={'_blank'}
                            href='https://yuque.antfin.com/cn-framework-committee/cn-ui-data-structure/cn-async-select#iEuF0'
                            rel='noreferrer'
                          >
                            接口文档
                          </a>{' '}
                          <CnTooltip v2 align={'t'} trigger={<a>接口预览</a>}>
                            <div style={{ width: '200px', height: '260px' }}>
                              <img
                                style={{ width: '100%' }}
                                src='https://img.alicdn.com/imgextra/i1/O1CN01W5SNFR25Fg4QyRC53_!!6000000007497-0-tps-456-570.jpg'
                              />
                            </div>
                          </CnTooltip>
                        </div>
                      ),
                      buttonText: '选择请求API',
                      params: {
                        env: 'pre',
                        pageSize: 999,
                        // serviceType: 'HSF',
                      },
                      paramSetter: {
                        componentName: 'MixedSetter',
                        props: {
                          setters: [
                            paramSelectSetter,
                            {
                              componentName: 'StringSetter',
                              title: '字符串',
                            },
                            getJSExpressionPrototype({ type: 'formRequest' }),
                          ],
                        },
                      },
                      resultProcessFuncTemplate: `function(res) {
  // 需要返回的如下的数据结构
  // return {
  //   success: true,
  //   data: [
  //     {
  //        label:"xx",
  //        value:"xx",
  //     }
  //   ]
  // }
 return res;
}`,
                    },
                  },
                  // condition(prop) {
                  //   return condition(prop, 'Select', 'componentName') && prop?.parent?.getPropValue?.('mode') === 'multiple';
                  // },
                },
                {
                  name: 'searchKey',
                  title: '远程搜索时的key',
                  display: 'inline',
                  setter: {
                    componentName: 'StringSetter',
                    props: {},
                  },
                },
                {
                  name: 'hideMaxTag',
                  title: '隐藏已选项数',
                  display: 'inline',
                  setter: 'BoolSetter',
                },
                {
                  name: 'maxTagCount',
                  title: '最多显示多少个tag',
                  display: 'inline',
                  setter: 'NumberSetter',
                },
              ],
            },
          },
        },
        condition(prop) {
          const selectMode = prop?.parent?.getPropValue?.('mode');
          return (
            condition(prop, 'Select', 'componentName') &&
            (selectMode === 'multiple' || selectMode === 'tag')
          );
        },
      },
      ...getBizExtendPrototype({
        componentName: 'CnAsyncSelect',
      }),
      {
        title: '数据字段映射配置',
        name: 'fieldNames',
        display: 'accordion',
        extraProps: {
          defaultCollapsed: false,
        },
        setter: {
          componentName: 'ObjectSetter',
          props: {
            config: {
              items: [
                {
                  name: 'label',
                  title: '标签(label)字段映射',
                  tip: '用于指定下拉框数据源中用于显示的label字段需要映射的字段名，例如text。仅用于旧接口适配，请务必遵守数据规范',
                  setter: ['StringSetter', 'VariableSetter'],
                },
                {
                  name: 'value',
                  title: '值(value)字段映射',
                  tip: '用于指定下拉框数据源中用于传值的value字段需要映射的字段名，例如key。仅用于旧接口适配，请务必遵守数据规范',
                  setter: ['StringSetter', 'VariableSetter'],
                },
              ],
            },
          },
        },
      },
      {
        title: '高级配置',
        name: __advancedConfig__,
        display: 'accordion',
        extraProps: {
          defaultCollapsed: true,
        },
        setter: {
          componentName: 'ObjectSetter',
          props: {
            config: {
              items: [
                {
                  name: 'useVirtual',
                  title: '开启虚拟滚动',
                  setter: 'BoolSetter',
                },
                {
                  name: 'autoWidth',
                  title: '选项宽度与下拉框一致',
                  setter: 'BoolSetter',
                },
              ],
            },
          },
        },
      },
    ];
  },
};

CnAsyncSelect.filterBeforeHandler = (
  props,
  {
    isDesign,
    urlParamsDataSource,
    recordDataSource,
    state,
    componentRequestFinish,
    filterItemConfig,
    isInForm,
    formInstance,
    _context,
    getFormInstance,
    formItemConfig,
    formProps,
  },
) => {
  const { _dataSourceName } = formProps || {};
  const realName = filterItemConfig?.name || formItemConfig?.name;
  const newProps = cloneDeep(props);
  const {
    dataOrigin,
    requestConfig,
    dataSource,
    multipleExtraProps,
    manual,
    requestWhenFocus,
  } = newProps || {};
  const { serviceType, mockData, method } = requestConfig || {};
  const { initRequestConfig, hideMaxTag, maxTagCount } =
    multipleExtraProps || {};
  if (dataOrigin === 'static') {
    if (typeof dataSource === 'function') {
      try {
        const temp = dataSource(state);
        if (Array.isArray(temp)) {
          newProps.dataSource = temp;
        }
      } catch (e) {
        const tempTitle = formItemConfig?.label || formItemConfig?.name;
        console.error(`${tempTitle} 的数据源表达式执行错误`);
      }
    } else if (isValueObjectExpr(dataSource)) {
      const tempDs = calculateTextExprValue(dataSource, { state });
      if (Array.isArray(tempDs)) {
        newProps.dataSource = tempDs;
      } else {
        newProps.dataSource = [];
      }
    }
    if (!Array.isArray(newProps.dataSource)) {
      newProps.dataSource = [];
    }
    delete newProps.requestConfig;
  } else {
    if (isInForm) {
      newProps.getRequestParams = () => {
        return {
          state: _context?.state,
          recordDataSource,
        };
      };
    } else {
      const realUrl = getRealRequestUrl({
        requestConfig: newProps?.requestConfig,
        state,
        extraParam: {},
      });
      if (realUrl) {
        newProps.requestConfig.url = realUrl;
        delete newProps.requestConfig.dynamicUrl;
      }
      const execute = calculateRequestExecute(
        requestConfig,
        {
          [__dataSource__]: state,
        },
        recordDataSource || {},
        state,
      );
      if (execute === false) {
        if (newProps?.requestConfig) {
          newProps.requestConfig.manual = true;
        }
      }
      if (requestWhenFocus === false) {
      } else {
        newProps.onVisibleChange = visibleRun.bind(this, {
          requestConfig,
          state,
          recordDataSource,
        });
      }
    }
    if (dataOrigin === 'request') {
      delete newProps.dataSource;
    }
    if (newProps?.requestConfig?.serviceType === 'mokelay') {
      newProps.requestConfig.method = 'post';
      if (isDesign && newProps?.requestConfig?.url) {
        newProps.requestConfig.url = handleDesignMokelayUrl(
          newProps.requestConfig?.url,
        );
      }
    } else if (newProps?.requestConfig) {
      newProps.requestConfig.withCredentials = true;
    }

    if (
      Array.isArray(newProps?.requestConfig?.params) &&
      newProps?.requestConfig?.params.length > 0
    ) {
      const { params } = newProps.requestConfig;
      newProps.requestConfig.searchFormat = (
        originalParam,
        extraRequestParams,
      ) => {
        let realRecord = recordDataSource;
        let realState = state;
        if (isInForm) {
          if (typeof getFormInstance === 'function') {
            realRecord = getFormInstance()?.values;
          } else if (formInstance?.values) {
            realRecord = formInstance.values;
          }
          if (_context?.state) {
            realState = _context.state;
          }
        }
        const realParams = handleRequestParams(params, {
          urlParamsDataSource,
          recordDataSource: realRecord,
          state: realState,
          ...extraRequestParams,
        });
        const tempResult = { ...realParams, ...originalParam };
        if (
          serviceType === 'http' &&
          method === 'post' &&
          requestConfig?.contentType === formUrlencoded
        ) {
          return qs.stringify(tempResult);
        }
        return tempResult;
      };
      delete newProps.requestConfig.params;
    }

    // if(isInForm === true) {
    //   newProps.getRequestParams = ()=>{
    //     let temp1 = recordDataSource;
    //     let temp2 = state;
    //     if(formInstance?.values) {
    //       temp1 = formInstance.values;
    //     }
    //     if(_context?.state) {
    //       temp2 = _context?.state;
    //     }
    //     return {
    //       urlParamsDataSource,
    //       recordDataSource: temp1,
    //       state: temp2,
    //     }
    //   }
    // }else{
    //   if (Array.isArray(newProps?.requestConfig?.params) && newProps?.requestConfig?.params.length > 0) {
    //     const realParams = handleRequestParams(newProps?.requestConfig?.params, {
    //       urlParamsDataSource,
    //       recordDataSource,
    //       state,
    //     });
    //     if (realParams) {
    //       if (newProps?.requestConfig?.method === 'post') {
    //         newProps.requestConfig.data = realParams;
    //         delete newProps.requestConfig.params;
    //       } else {
    //         newProps.requestConfig.params = realParams;
    //       }
    //     }
    //   }
    // }
    if (typeof newProps?.requestConfig?.resultProcessFunc === 'function') {
      newProps.requestConfig.formatResult = (res) => {
        let newRes = getRealResponse(res);
        try {
          newRes = newProps?.requestConfig?.resultProcessFunc(newRes);
        } catch (e) {
          console.error('请求结果回调执行失败', e);
        }

        if (Array.isArray(newRes?.data)) {
          newRes = newRes.data;
        } else if (Array.isArray(newRes?.data?.dataSource)) {
          newRes = newRes?.data?.dataSource;
        }
        componentRequestFinish?.({ name: realName, dataSource: newRes });
        return newRes;
      };
    } else if (serviceType === 'mock' && isPlainObject(mockData)) {
      newProps.requestConfig.formatResult = () => {
        componentRequestFinish?.({
          name: realName,
          dataSource: mockData?.data,
        });
        return mockData?.data;
      };
    } else if (newProps?.requestConfig) {
      newProps.requestConfig.formatResult = (res) => {
        let newRes = getRealResponse(res);
        if (Array.isArray(newRes?.data)) {
          newRes = newRes.data;
        } else if (Array.isArray(newRes?.data?.dataSource)) {
          newRes = newRes?.data?.dataSource;
        }
        componentRequestFinish?.({ name: realName, dataSource: newRes });
        return newRes;
      };
    }
    if (newProps?.searchRemote) {
      newProps.filterLocal = false;
      if (newProps?.searchKey && newProps?.requestConfig) {
        newProps.requestConfig.searchKey = newProps.searchKey;
      }
    }
    if (newProps?.requestConfig) {
      newProps.requestConfig.throttleWait = 800;
    }

    if (newProps?.mode === 'multiple' || newProps?.mode === 'tag') {
      if (hideMaxTag === true) {
        newProps.maxTagPlaceholder = () => {
          return null;
        };
      }
      if (typeof maxTagCount === 'number') {
        newProps.maxTagCount = maxTagCount;
        newProps.tagInline = false;
      }
      if (initRequestConfig) {
        const realInitUrl = getRealRequestUrl({
          requestConfig: initRequestConfig,
          state,
        });
        if (realInitUrl) {
          initRequestConfig.url = realInitUrl;
        }
        const tempProps = {
          dataOrigin: 'request',
          requestConfig: initRequestConfig,
        };
        handleSelectRequestConfig({
          componentProps: tempProps,
          isDesign,
          urlParamsDataSource,
          recordDataSource,
          state,
        });
        if (tempProps?.requestConfig) {
          newProps.initRequestConfig = {
            ...tempProps.requestConfig,
          };
          if (multipleExtraProps?.searchKey) {
            newProps.initRequestConfig.searchKey = multipleExtraProps.searchKey;
          }
        }
      }
    } else {
      delete newProps?.initRequestConfig;
    }
    if (manual === true && newProps?.requestConfig) {
      newProps.requestConfig.manual = true;
    }
  }

  delete newProps.searchRemote;
  delete newProps.searchKey;
  delete newProps.manual;
  newProps.showSearch = true;

  newProps.autoWidth = false;
  if (newProps.mode === 'single') {
    delete newProps.hasSelectAll;
  }

  delete newProps.multipleExtraProps;
  setAdvancedConfigToProps(newProps);
  handleFormUrlencodedContentType(newProps?.requestConfig);
  newProps._dataSourceName = _dataSourceName;
  return newProps;
};
CnAsyncSelect.formBeforeHandler = CnAsyncSelect.filterBeforeHandler;
export default Select;
