import { Component, Suspense, type ErrorInfo, type ReactNode } from "react";
import Button from "./Button";
import DismissibleAlert from "./DismissibleAlert";
import LoadingIndicator from "./LoadingIndicator";

type ModuleLoadBoundaryProps = {
  children: ReactNode;
  resetKey: string;
  loading?: boolean;
};

type ModuleLoadBoundaryState = {
  error: Error | null;
};

export default class ModuleLoadBoundary extends Component<
  ModuleLoadBoundaryProps,
  ModuleLoadBoundaryState
> {
  state: ModuleLoadBoundaryState = { error: null };

  static getDerivedStateFromError(error: Error): ModuleLoadBoundaryState {
    return { error };
  }

  componentDidCatch(error: Error, info: ErrorInfo) {
    console.error("GovOPlaN module route failed to load", error, info);
  }

  componentDidUpdate(previousProps: ModuleLoadBoundaryProps) {
    if (
      previousProps.resetKey !== this.props.resetKey &&
      this.state.error
    ) {
      this.setState({ error: null });
    }
  }

  render() {
    if (this.props.loading) {
      return <ModuleLoadProgress />;
    }
    if (this.state.error) {
      return (
        <div className="content-pad module-load-error">
          <DismissibleAlert tone="danger" dismissible={false}>
            <p>i18n:govoplan-core.the_resource_could_not_be_loaded.0d1b6cbf</p>
            <Button type="button" onClick={() => window.location.reload()}>
              i18n:govoplan-core.reload.cce71553
            </Button>
          </DismissibleAlert>
        </div>
      );
    }

    return (
      <Suspense
        fallback={<ModuleLoadProgress />}
      >
        {this.props.children}
      </Suspense>
    );
  }
}

function ModuleLoadProgress() {
  return (
    <div className="content-pad module-load-progress">
      <LoadingIndicator
        label="i18n:govoplan-core.loading_module.50161f3c"
        size="md"
      />
      <span>i18n:govoplan-core.loading_module.50161f3c</span>
    </div>
  );
}
