// @flow
import type { Node } from 'react';
import React from 'react';
import Yrbl from 'component/yrbl';
import Button from 'component/button';
import { withRouter } from 'react-router';
import analytics from 'analytics';
import I18nMessage from 'component/i18nMessage';
import Native from 'native';
import { Lbry } from 'lbry-redux';

type Props = {
  children: Node,
  history: {
    replace: (string) => void,
  },
};

type State = {
  hasError: boolean,
  sentryEventId: ?string,
  desktopErrorReported: boolean,
};

class ErrorBoundary extends React.Component<Props, State> {
  constructor() {
    super();
    this.state = { hasError: false, sentryEventId: undefined, desktopErrorReported: false };

    (this: any).refresh = this.refresh.bind(this);
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // @if TARGET='web'
    analytics.sentryError(error, errorInfo).then((sentryEventId) => {
      this.setState({ sentryEventId });
    });
    // @endif

    // @if TARGET='app'
    let errorMessage = 'Uncaught error\n';
    Native.getAppVersionInfo().then(({ localVersion }) => {
      Lbry.version().then(({ lbrynet_version: sdkVersion }) => {
        errorMessage += `app version: ${localVersion}\n`;
        errorMessage += `sdk version: ${sdkVersion}\n`;
        errorMessage += `page: ${window.location.href.split('.html')[1]}\n`;
        errorMessage += `${error.stack}`;
        analytics.error(errorMessage).then((isSharingData) => {
          this.setState({ desktopErrorReported: isSharingData });
        });
      });
    });
    // @endif
  }

  refresh() {
    const { history } = this.props;

    // use history.replace instead of history.push so the user can't click back to the errored page
    history.replace('');
    this.setState({ hasError: false });
  }

  render() {
    const { hasError } = this.state;
    const { sentryEventId, desktopErrorReported } = this.state;

    const errorWasReported = IS_WEB ? sentryEventId !== null : desktopErrorReported;

    if (hasError) {
      return (
        <div className="main main--full-width main--empty">
          <Yrbl
            type="sad"
            title={__('Aw shucks!')}
            subtitle={
              <I18nMessage
                tokens={{
                  refreshing_the_app_link: (
                    <Button
                      button="link"
                      className="load-screen__button"
                      label={__('refreshing the app')}
                      onClick={this.refresh}
                    />
                  ),
                }}
              >
                There was an error. Try %refreshing_the_app_link% to fix it. If that doesn't work, try pressing
                Ctrl+R/Cmd+R.
              </I18nMessage>
            }
          />
          {!errorWasReported && (
            <div className="error__wrapper">
              <span className="error__text">
                {__('You are not currently sharing diagnostic data so this error was not reported.')}
              </span>
            </div>
          )}

          {errorWasReported && (
            <div className="error__wrapper">
              {/* @if TARGET='web' */}
              <span className="error__text">{__('Error ID: %sentryEventId%', { sentryEventId })}</span>
              {/* @endif */}
              {/* @if TARGET='app' */}
              <span className="error__text">{__('This error was reported and will be fixed.')}</span>
              {/* @endif */}
            </div>
          )}
        </div>
      );
    }

    return this.props.children;
  }
}

export default withRouter(ErrorBoundary);
