import * as React from 'react';
import { useLocation } from 'react-router-dom';
import { runtime } from './adapter';
import { app as _app } from '../app/global-api';
import { widgetKeys } from './widgets';

export function useScrollTop() {
  const { pathname } = useLocation();
  React.useEffect(() => {
    runtime?.scrollTo(0, 0);
  }, [pathname]);
  return null;
}

/**
 * 用于处理自定义组件props传参结构，对系统变量进行保留
 * 曾用名：resolveComponentProps()
 */
export function useComponentProps(props: IFieldProps, isPlainProps) {
  const emitRef = React.useRef(props.emit);
  const { __internal__ = {} } = _app || {};
  const { resolveStaticResourceUrl } = __internal__ || ({} as any);
  const reactBuiltinPorps = React.useMemo(
    () => ['ref', 'key', 'dangerouslySetInnerHTML', 'className', 'htmlFor', 'style', 'contentEditable', 'children'],
    [],
  );
  const builtinProps = React.useMemo(
    () => [
      // react 保留字
      ...reactBuiltinPorps,
      // lowcode 保留字
      ...widgetKeys,
      'events',
      'classList',
      'widgetType',
      'staticResourceAttribute',
      // 小程序保留字
      'id',
      'class',
      'hidden',
      'slot',
    ],
    [],
  );
  const {
    data = {},
    staticResourceAttribute,
    emit,
    events,
    /**
     * 排除复合组件所需独有属性
     */
    compositeParent: _,
    forIndexes: __,
    ...restProps
  } = props;
  staticResourceAttribute?.map?.((property) => {
    if (props.data?.[property]) {
      props.data[property] = resolveStaticResourceUrl(props.data[property]);
    }
  });
  if (!isPlainProps) {
    return props;
  }
  const customProps = { ...data };

  // delete builtin props
  builtinProps.map((prop) => delete customProps[prop]);
  // 选区events处理
  const { _selectableBlockEvents, ...restData } = customProps;
  const { emit: _selectableBlockEmit } = _selectableBlockEvents;

  _selectableBlockEvents.events = new Proxy(
    {},
    {
      get(obj, prop) {
        return prop in obj ? obj[prop] : (e) => _selectableBlockEmit(prop, e);
      },
    },
  );

  emitRef.current = emit;
  /**
   * TODO: 可不依赖配置的事件列表，使用通用 proxy
   * 但存在问题：vue.CreateElement 中 on 可能遍历了 events 对象
   * proxy 会导致获取不到事件
   */
  const proxyEvents = React.useMemo(() => {
    return new Proxy(
      events.reduce((events, item) => {
        const propName = item;
        events[propName] = (e) => emitRef.current(propName, e);
        return events;
      }, {}),
      {
        get(obj, prop) {
          return prop in obj ? obj[prop] : (e) => emitRef.current(prop, e);
        },
      },
    );
  }, [emitRef, events]);

  return {
    ...restData,
    ...restProps,
    _selectableBlockEvents,
    /**
     * 覆盖原有的 events 事件名数组，采用通用代理
     */
    events: proxyEvents,
    emit,
  };
}

export interface IFieldProps extends React.PropsWithRef<any> {
  id: string;
  data: any;
  emit: (trigger, eventData, domEvent?) => void;
  events: string[];
  /**
   * current widget
   */
  $node: any;
  staticResourceAttribute: string[];
  domRef: React.RefObject<any>;

  compositeParent: any;
  forIndexes: number[];
}
