import React from "react";

interface Props {
  children: React.ReactNode;
  /** The <select> to reveal on error so users still see native WooCommerce dropdowns. */
  fallbackSelect?: HTMLSelectElement | null;
}

interface State {
  hasError: boolean;
}

/**
 * React error boundary for swatch components.
 *
 * On error, reveals the native WooCommerce <select> dropdown so the
 * product page remains functional even if the swatch UI crashes.
 */
class SwatchErrorBoundary extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false };
  }

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

  componentDidCatch(error: Error, info: React.ErrorInfo): void {
    // Log for debugging but don't break the page.
    if (typeof console !== "undefined") {
      // eslint-disable-next-line no-console
      console.error("[B3 Swatches] Render error:", error, info.componentStack);
    }
  }

  componentDidUpdate(_prevProps: Props, prevState: State): void {
    // When we enter the error state, reveal the native select.
    if (this.state.hasError && !prevState.hasError) {
      this.revealFallbackSelect();
    }
  }

  private revealFallbackSelect(): void {
    const { fallbackSelect } = this.props;
    if (!fallbackSelect) return;

    // Show the original WooCommerce select dropdown.
    const wrapper = fallbackSelect.closest<HTMLElement>(
      ".b3-wvs-original-select",
    );
    if (wrapper) {
      wrapper.style.display = "";
    }

    // Also remove the initialized class so CSS fallback styles apply.
    const container = fallbackSelect.closest<HTMLElement>(
      ".b3-wvs-swatches-container",
    );
    if (container) {
      container.classList.remove("b3-wvs-initialized");
      container.classList.add("b3-wvs-fallback");
    }
  }

  render(): React.ReactNode {
    if (this.state.hasError) {
      // Render nothing — the native <select> is revealed above.
      return null;
    }
    return this.props.children;
  }
}

export default SwatchErrorBoundary;
