import React, {
  useCallback,
  useMemo,
  useEffect,
  useRef,
  useState,
  forwardRef,
  useImperativeHandle,
} from 'react';
import {
  CnFilter as UICnFilter,
  formilyCore,
  CnFilterItem,
} from '@cainiaofe/cn-ui-m';
import {
  calculateWaitComponentList,
  executeEventWithoutJS,
  executeObjectExpr,
  getFormDefaultValue,
  isArrayNotEmpty,
  isDesignMode,
  isEmptyButNotZero,
  makeFormItemSchema,
  transProxyToObject,
} from '@/common/util/util';
import isEqualWith from 'lodash/isEqualWith';
import isPlainObject from 'lodash/isPlainObject';
import cloneDeep from 'lodash/cloneDeep';
import cloneDeepWith from 'lodash/cloneDeepWith';
import { toJS } from '@formily/reactive';
import {
  CnFilterDefaultValueFinished,
  CnFilterOnChange,
  CnFilterOnSearch,
  CnPageRequestFinish,
  emitEvent,
  onEvent,
} from '@/common/util/event-name';
import {
  __dataSource__,
  __filterValue__,
  __formValue__,
} from '@/common/util/expr-const';
import isEmpty from 'lodash/isEmpty';
import { ButtonPosition } from '@/type/button-position';
import { getButtonAction } from '@/common/manager/button';
import { dataOriginStatic, dataOriginRequest } from '@/common/util/const';
import { getFormExtraComponents } from '@/common/manager/filter-item';

const {
  createForm,
  onFormValuesChange,
  onFieldReact,
  onFieldInputValueChange,
} = formilyCore || {};

function View(props, ref) {
  const {
    config = [],
    _dataSource,
    _dataSourceName,
    _context,
    forwardedRef,
    _bindTable,
    defaultParams,
    filterStyle,
    title,
    events: filterEvents,
    ...otherProps
  } = props;
  const isDesign = isDesignMode(props);
  const formInstance = useRef(null);
  const urlParams = _context?.state?.urlParams || {};
  const oldSchema = useRef(null);
  let extraProps = {};
  const usedComponentList = [];
  const filterRef = useRef(null);
  const { dataOrigin, deferRender } = defaultParams || {};
  // 记录默认值请求需要等待哪些组件请求完成
  const waitComponentList = useRef([]);
  const configMap = useRef({});
  let defaultDeferRender;
  if (!isDesign && dataOrigin === dataOriginRequest && !!deferRender) {
    defaultDeferRender = !!deferRender;
  }
  const [defer, setDefer] = useState(defaultDeferRender);
  const [forceUpdate, setForceUpdate] = useState();
  // 缓存默认值，用于重置还原
  const cacheDefaultValue = useRef(null);
  const { afterResetNeedQuery } = filterStyle || {};

  useImperativeHandle(ref, () => ({
    reset() {
      formInstance?.current?.filterReset?.();
    },
    getFormInstance() {
      return formInstance.current;
    },
    search() {
      formInstance?.current?.handleSearch?.();
    },
  }));

  const getFormValue = useCallback(() => {
    if (typeof _dataSource === 'object') {
      return transProxyToObject(_dataSource);
    }
    return null;
  }, []);

  const componentRequestFinish = useCallback((tempConfig) => {
    const { name, dataSource } = tempConfig || {};
    const defaultValues = cacheDefaultValue.current;
    const oldLength = waitComponentList.current?.length;
    if (
      isPlainObject(defaultValues) &&
      name &&
      waitComponentList.current?.includes(name)
    ) {
      waitComponentList.current = waitComponentList.current.filter(
        (item) => item !== name,
      );
      const current = defaultValues[name];
      if (
        typeof current?.value === 'number' &&
        current?.valueType === 'DefaultSelect'
      ) {
        const currentConfig = configMap?.current?.[name];
        const temp = dataSource?.[current.value];
        let realValue = temp?.value;
        if (currentConfig?.options?.mode === 'multiple') {
          if (isEmptyButNotZero(realValue)) {
            realValue = [];
          } else {
            realValue = [realValue];
          }
        }
        defaultValues[name] = realValue;
      }
      const newLength = waitComponentList.current.length;
      if (newLength === 0 && oldLength > 0) {
        formInstance?.current?.setInitialValues(defaultValues);
        const table = _context?.$(_bindTable);
        if (table?.props?.manual === true) {
        } else {
          setTimeout(() => {
            tableLoad();
          });
        }
      }
    }
  }, []);

  // 设计态默认值的兼容逻辑
  if (isDesign === true) {
    if (dataOrigin === dataOriginStatic) {
      const tempDefaultValue = getFormDefaultValue(defaultParams, {
        urlParamsDataSource: urlParams,
        state: _context?.state,
        isDesign,
        formConfig: config,
      });
      if (isPlainObject(tempDefaultValue)) {
        formInstance?.current?.setValues?.(tempDefaultValue, 'overwrite');
      }
    }
  }

  const getRemoteDefaultValue = () => {
    const {
      dataOrigin,
      requestConfig = {},
      afterRequest = {},
    } = defaultParams || {};

    if (dataOrigin === 'request') {
      const p = getFormDefaultValue(defaultParams, {
        urlParamsDataSource: urlParams,
        state: _context?.state,
        isDesign,
        formConfig: config,
      });
      let newFormValue;
      if (p?.then) {
        p.then(
          (result) => {
            if (isPlainObject(result)) {
              newFormValue = { ...(result || {}) };
              formInstance?.current?.setInitialValues?.(
                cloneDeep(newFormValue),
                'overwrite',
              );
            }
            setDefer(false);
            emitEvent(CnFilterDefaultValueFinished, {
              componentProps: props,
              formValues: newFormValue,
            });
          },
          () => {
            setDefer(false);
            emitEvent(CnFilterDefaultValueFinished, {
              componentProps: props,
            });
          },
        ).then((res) => {
          if (afterRequest?.optType) {
            const action = getButtonAction({
              ...afterRequest,
              position: ButtonPosition.filterDefaultValueAfterRequestSuccess,
            });
            action?.({
              position: ButtonPosition.filterDefaultValueAfterRequestSuccess,
              urlParamsDataSource: urlParams,
              recordDataSource: newFormValue,
              state: _context?.state,
              buttonConfig: afterRequest,
              _context,
            });
          }
        });
      }
    }
  };

  const getStaticDefaultValue = (originalFormValue, extraConfig) => {
    let result = originalFormValue;
    if (dataOrigin === dataOriginStatic) {
      const p = getFormDefaultValue(defaultParams, {
        urlParamsDataSource: urlParams,
        state: _context?.state,
        isDesign,
        formConfig: config,
        ...extraConfig,
      });
      if (isPlainObject(p)) {
        result = { ...(originalFormValue || {}), ...(p || {}) };
      }
    }
    return result;
  };

  // didMount查询默认值
  useEffect(() => {
    getRemoteDefaultValue();
    onEvent(CnPageRequestFinish, () => {
      setForceUpdate(Date.now());
    });
    return () => {
      if (_dataSourceName) {
        const temp = _context?.state?.[_dataSourceName];
        if (isPlainObject(temp) && !isEmpty(temp)) {
          _context?.setState({
            [_dataSourceName]: {},
          });
        }
      }
    };
  }, []);

  const generateForm = (formValue, otherConfig) => {
    const { setInitialValues } = otherConfig || {};
    const formOptions = {
      effects() {
        onFormValuesChange((form) => {
          if (form?.values) {
            const temp = cloneDeep(toJS(form.values));
            if (_dataSourceName && temp) {
              _context?.setState({
                [_dataSourceName]: temp,
              });
            }
            emitEvent(CnFilterOnChange, {
              componentProps: props,
              payload: form?.values,
            });
            tableForceUpdate();
          }
        });

        function handleConfig(list) {
          if (isArrayNotEmpty(list)) {
            for (const item of list) {
              const { events, name, componentName, options, hidden, disabled } =
                item || {};
              if (name) {
                const fieldName = name;
                if (isArrayNotEmpty(events)) {
                  for (const event of events) {
                    const {
                      name: eventName,
                      optType,
                      jsFunction,
                    } = event || {};
                    let hook;
                    if (eventName === 'onFieldValueChange') {
                      hook = onFieldInputValueChange;
                    }
                    if (hook) {
                      if (
                        optType === 'jsAction' &&
                        typeof jsFunction === 'function'
                      ) {
                        hook(fieldName, (field) => {
                          jsFunction.call(null, field, formInstance.current);
                        });
                      } else {
                        const action = getButtonAction({
                          ...event,
                          position: ButtonPosition.filterItemEvent,
                        });
                        if (typeof action === 'function') {
                          const callback = (field) => {
                            action({
                              buttonConfig: {
                                ...event,
                                position: ButtonPosition.filterItemEvent,
                                options: {
                                  ...event,
                                },
                              },
                              position: ButtonPosition.filterItemEvent,
                              componentProps: props,
                              state: _context?.state,
                              urlParamsDataSource: urlParams,
                              recordDataSource: {
                                realize: () => {
                                  return formInstance?.current?.values;
                                },
                              },
                              formInstance: {
                                realize: () => {
                                  return formInstance?.current;
                                },
                              },
                              _context,
                              field,
                            });
                          };
                          hook(fieldName, callback);
                        }
                      }
                    }
                  }
                }

                if (hidden !== undefined && hidden !== '' && hidden !== false) {
                  onFieldReact(fieldName, (field, form) => {
                    const objExprArgMap = {
                      [__dataSource__]: _context?.state,
                      [__formValue__]: form?.values,
                      [__filterValue__]: form?.values,
                    };
                    const isHidden = executeObjectExpr(
                      hidden,
                      objExprArgMap,
                      form?.values || {},
                      _context?.state,
                    );
                    if (isHidden === true) {
                      field.hidden = true;
                    } else {
                      field.hidden = false;
                    }
                  });
                }
                if (
                  disabled !== undefined &&
                  disabled !== '' &&
                  disabled !== false
                ) {
                  onFieldReact(fieldName, (field, form) => {
                    const objExprArgMap = {
                      [__dataSource__]: _context?.state,
                      [__formValue__]: form?.values,
                      [__filterValue__]: form?.values,
                    };
                    field.disabled = executeObjectExpr(
                      disabled,
                      objExprArgMap,
                      form?.values || {},
                      _context?.state,
                    );
                  });
                }
              }
            }
          }
        }
        handleConfig(config);
      },
    };
    if (formValue && Object.keys(formValue).length > 0) {
      if (setInitialValues) {
        formOptions.initialValues = cloneDeep(formValue);
      } else {
        formOptions.values = cloneDeep(formValue);
      }
    }
    return createForm(formOptions);
  };

  if (!formInstance.current) {
    const formDefaultValue = getFormValue();
    const tempResult = calculateWaitComponentList(config, defaultParams);
    if (isArrayNotEmpty(tempResult.waitComponentList)) {
      waitComponentList.current = tempResult.waitComponentList;
    }
    if (!isEmpty(tempResult.configMap)) {
      configMap.current = tempResult.configMap;
    }
    let staticFormDefaultValue = getStaticDefaultValue(formDefaultValue);
    if (isArrayNotEmpty(waitComponentList?.current)) {
      cacheDefaultValue.current = staticFormDefaultValue;
      staticFormDefaultValue = getStaticDefaultValue(formDefaultValue, {
        ignoreDefaultSelectFormRequest: true,
      });
    } else if (_dataSourceName && isPlainObject(staticFormDefaultValue)) {
      if (dataOrigin === dataOriginStatic) {
        emitEvent(CnFilterDefaultValueFinished, {
          componentProps: props,
          formValues: staticFormDefaultValue,
        });
      }
      _context?.setState({
        [_dataSourceName]: staticFormDefaultValue,
      });
    }

    formInstance.current = generateForm(staticFormDefaultValue, {
      setInitialValues: true,
    });
  }

  const onSearch = useCallback((value) => {
    emitEvent(CnFilterOnSearch, {
      componentProps: props,
      payload: value,
    });
    executeEventWithoutJS({
      eventType: 'onSearch',
      events: filterEvents,
      _context,
      position: ButtonPosition.filterEvent,
      urlParamsDataSource: urlParams,
      recordDataSource: value,
    });
    tableLoad();
  }, []);

  const generateFormItemSchema = (item) => {
    const formValue = toJS(formInstance.current?.values);

    const formItem = makeFormItemSchema({
      formValue,
      formItemConfig: item,
      isDesign,
      urlParams,
      state: _context?.state,
      usedComponentList,
      formProps: props,
      _context,
      formInstance: formInstance?.current,
      getFormInstance: () => {
        return formInstance.current;
      },
      isInCnFilterPro: true,
      // 当组件请求完成时，调用回调告知表单组件我已请求完成，从而实现下拉框默认勾选第一项操作
      componentRequestFinish,
      customDecoratorComponent: 'CnFilterProItem',
    });
    if (formItem) {
      return formItem;
    }
  };

  const tableForceUpdate = useCallback(() => {
    if (_bindTable && _context) {
      const table = _context?.$?.(_bindTable);
      table?.forceUpdate?.();
    }
  }, []);

  const tableLoad = useCallback(() => {
    if (_bindTable && _context) {
      const table = _context.$(_bindTable);
      table?.load?.();
    }
  }, []);

  // 自定义的onReset，用于避免触发表格重新查询
  const onReset = useCallback(() => {
    // tableForceUpdate();
  }, []);

  const generateSchema = () => {
    const tree = {
      type: 'object',
      properties: {},
    };
    const newConfig = cloneDeepWith(config, (value) => {
      if (React.isValidElement(value)) {
        return value;
      }
    });
    // const originalConfigMap = {}
    // config.forEach((item,index)=>{
    //   if(item?.name && item?.componentName) {
    //     originalConfigMap[item.name] = {
    //       ...item,
    //     };
    //   }
    // })
    newConfig.forEach((item, index) => {
      const { name, componentName } = item || {};
      if (name && componentName) {
        const current = generateFormItemSchema(item);
        current._name = name;
        current._componentName = componentName;
        current._parent = 'root';
        if (current) {
          tree.properties[name] = current;
        }
      }
    });
    return tree;
  };

  const generateDom = () => {
    const result = [];
    const newConfig = cloneDeepWith(config, (value) => {
      if (React.isValidElement(value)) {
        return value;
      }
    });
    newConfig.forEach((item, index) => {
      const { name, componentName, label, quick } = item || {};
      if (name && componentName) {
        const current = generateFormItemSchema(item);
        const CurrentComponent = window.CNUIM?.[componentName];
        if (CurrentComponent) {
          result.push(
            <CnFilterItem title={label} name={name} quick={quick}>
              <CurrentComponent {...current?.['x-component-props']} />
            </CnFilterItem>,
          );
        }
      }
    });
    return result;
  };

  const dom = generateDom();
  // let needCreateNewForm = false;
  const schema = generateSchema();
  // if (schema && oldSchema.current) {
  //   if (!isEqualWith(schema, oldSchema.current,(objValue, othValue)=>{
  //     if(objValue instanceof Function && othValue instanceof Function) {
  //       return true;
  //     }
  //   })) {
  //     needCreateNewForm = true
  //   }
  // }

  // if(needCreateNewForm) {
  //   console.log('new filter pro');
  // formInstance.current = generateForm(toJS(formInstance.current?.values));
  // }
  // oldSchema.current = { ...schema };

  if (isPlainObject(filterStyle)) {
    extraProps = {
      ...extraProps,
      ...filterStyle,
    };
  }

  if (!isDesign && defer) {
    return null;
  }

  if (afterResetNeedQuery === false) {
    extraProps.onReset = onReset;
  }

  const formComponents = getFormExtraComponents(usedComponentList);
  return (
    <UICnFilter
      ref={filterRef}
      onSearch={onSearch}
      form={formInstance.current}
      // schema={schema}
      components={formComponents}
      {...extraProps}
    >
      {dom}
    </UICnFilter>
  );
}

const CnFilter = forwardRef(View);

CnFilter.displayName = 'CnFilter';

export { CnFilter };
