import * as React from "react";
import pick from "lodash/pick";

import { coreLogger } from "@applicaster/zapp-react-native-utils/logger";
import { ErrorScreen } from "@applicaster/zapp-react-native-ui-components/Components/ErrorScreen";

import { useErrorStore } from "./store";
import * as QuickBrickManager from "@applicaster/zapp-react-native-bridge/QuickBrick";

const errorBoundaryLogger = coreLogger.addSubsystem("react_error-boundary");

type Props = {
  children: React.ReactNode;
  recoverable?: boolean;
};

type ErrorBoundaryContentProps = {
  children: React.ReactNode;
};

const restartApp = () => {
  QuickBrickManager.sendQuickBrickEvent(
    QuickBrickManager.QUICK_BRICK_EVENTS.FORCE_APP_RELOAD
  );
};

const restartButton = {
  text: "Restart the app",
  onPress: restartApp,
};

const buttons = [restartButton];

const ErrorBoundaryContent: React.FC<ErrorBoundaryContentProps> = ({
  children,
}) => {
  const { hasError, dismissError, info } = pick(
    useErrorStore((state) => state),
    ["hasError", "dismissError", "info"]
  );

  if (hasError) {
    return (
      <ErrorScreen
        dismissError={dismissError}
        message={info}
        buttons={buttons}
      />
    );
  }

  return <>{children}</>;
};

export class ErrorBoundary extends React.Component<Props> {
  componentDidCatch(error, info) {
    errorBoundaryLogger.error({ error, data: info, message: error.message });
    const { recoverable = true } = this.props;

    useErrorStore.getState().setError(error, info, recoverable);
  }

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

  render() {
    return <ErrorBoundaryContent>{this.props.children}</ErrorBoundaryContent>;
  }
}
