import React, { PureComponent, ComponentType, createContext } from 'react';
import * as Sentry from '@sentry/browser';
import TryCatchView from './tryCatchView';
  
 
interface Error {
  name: string;
  message: string;
  stack?: string;
  code?: string;
}
 
const noop: (e: Error=> void = () => {};
const SentryContext = createContext({
  captureException: noop,
});
 
type SentryAppProps = {
  appVersion: string;
  appEnv: string;
  appName: string;
  errorFallback?: ComponentType<{ error: ErrorerrorHandler?: () => void }>; // 应急Error视图, 这个属性待定
  errorHandler?: () => void// 配置errorFallback 使用 @example const errorHandle = () => window.location.reload(true)
  getUserId: () => string// 获取用户id
  dsn: string// 获取用户sentry的远程数据源 dsn
};
 
  
 
type SentryAppState = {
  hasError: boolean;
  sentryInitialized: boolean;
  error: Error | undefined;
};
 
  
 
type ReactErrorStackInfo = { [key: string]: anycomponentStack?: any };
 
class SentryApp extends PureComponent<SentryAppPropsSentryAppState> {
  constructor(props: SentryAppProps) {
    super(props);
    this.state = {
      sentryInitialized: false,
      hasError: false,
      error: undefined,
    };
  }
 
  static getDerivedStateFromError() {
    return { hasError: true };
  }
 
  
 
  componentDidCatch(error: anyerrorInfo: ReactErrorStackInfo) {
    this.captureException(error, errorInfo);
  }
 
  
  componentDidMount() {
    this.setState({ sentryInitialized: true });
    const { dsn } = this.props;
 
    Sentry.init({
      dsn,
      integrationsintegrations => {
        const newIntegrations = integrations
          .map(integration => {
            if (integration.name === 'Breadcrumbs') {
              return new Sentry.Integrations.Breadcrumbs({
                console: false// Log calls to `console.log`, `console.debug`, etc
                dom: false// Log all click and keypress events
                fetch: false// Log HTTP requests done with the Fetch API
                history: false// Log calls to `history.pushState` and friends
                sentry: false// Log whenever we send an event to the server
                xhr: false// Log HTTP requests done with the XHR API
              });
            }
            return integration;
          })
          // 禁止 TryCatch & GlobalHandlers 每次error不产生额外的error
          .filter(integration => integration.name !== 'TryCatch' && integration.name !== 'GlobalHandlers');
        return newIntegrations;
      },
    });
  }
 
  
 
  /**
 
   * @description 备用字段 等待后续需求
 
   */
 
  eventId: string = '';
 
  captureException = (error: ErrorerrorInfo?: ReactErrorStackInfo=> {
    const { getUserIdappVersionappNameappEnv } = this.props;
    const userId = getUserId() || '';
    // 禁止 非integration定义error
    // 1、js load Error: ChunkLoadError 每次error不产生额外的error
    // 2、css chunk error: CSS_CHUNK_LOAD_FAILED 每次error不产生额外的error
    const { namecode } = error || {};
    if (name === 'ChunkLoadError' || code === 'CSS_CHUNK_LOAD_FAILED') {
      this.setState({
        error,
      });
      return;
    }
 
    Sentry.withScope(scope => {
      if (errorInfo) {
        scope.setExtras(errorInfo);
      }
      scope.setTag('meijian.user.id', userId);
      scope.setTag('meijian.app.version', appVersion);
      scope.setTag('meijian.app.name', appName);
      scope.setTag('meijian.app.env', appEnv);
      this.eventId = Sentry.captureException(error);
      this.setState({
        error,
      });
    });
  };
 
  errorHandler = {
    captureException: this.captureException,
  };
 
  
  render() {
    const { childrenerrorHandler } = this.props;
    const { hasErrorsentryInitializederror } = this.state;
    if (!sentryInitialized) {
      return null;
    }
    if (hasError) {
      return error ? <TryCatchView error={error} errorHandler={errorHandler} /> : null;
    }
    return <SentryContext.Provider value={this.errorHandler}>{children}</SentryContext.Provider>;
  }
}
 
export { SentryContext };
export { SentryApp };
export { SentryApp as default };