import { Component } from "react";
import type { ReactNode, ErrorInfo } from "react";
import { resolveLocaleFromPath, localeToLanguage } from "@/i18n/resolver.js";

export interface ErrorBoundaryProps {
  children: ReactNode;
  fallback?: ReactNode;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error: Error | null;
}

/**
 * Hand-rolled localised strings for the boundary. We can't call
 * `useTranslation()` here (class component, AND the i18n provider may
 * not exist when the error fires), so we read the locale from the URL
 * and fall back to English for any language we don't have coverage
 * for. Mirrors what Angular's global ErrorHandler renders.
 */
const FALLBACK_RU = { title: "Что-то пошло не так", retry: "Повторить" } as const;
const FALLBACK_EN = { title: "Something went wrong", retry: "Retry" } as const;

const FALLBACK_STRINGS: Record<string, { title: string; retry: string }> = {
  ru: FALLBACK_RU,
  en: FALLBACK_EN,
  es: { title: "Algo salió mal", retry: "Reintentar" },
  fr: { title: "Une erreur s'est produite", retry: "Réessayer" },
  it: { title: "Qualcosa è andato storto", retry: "Riprova" },
  de: { title: "Etwas ist schiefgelaufen", retry: "Wiederholen" },
  ja: { title: "問題が発生しました", retry: "再試行" },
  ko: { title: "문제가 발생했습니다", retry: "다시 시도" },
  zh: { title: "出错了", retry: "重试" },
};

function pickStrings(): { title: string; retry: string } {
  if (typeof window === "undefined") return FALLBACK_RU;
  const locale = resolveLocaleFromPath(window.location.pathname);
  const lang = locale ? localeToLanguage(locale) : "ru";
  return FALLBACK_STRINGS[lang] ?? FALLBACK_EN;
}

/**
 * React error boundary that catches render-time exceptions in the subtree.
 * Displays a minimal fallback UI with a "Retry" button that resets state.
 *
 * Must be a class component — React requires componentDidCatch / getDerivedStateFromError.
 */
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  override state: ErrorBoundaryState = { hasError: false, error: null };

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error };
  }

  override componentDidCatch(error: Error, info: ErrorInfo): void {
    // Phase 1G-logger will replace this with useLogger() context logging.
    // For now, write to console so errors are not silently swallowed.
    console.error("[ErrorBoundary]", error, info.componentStack);
  }

  private readonly handleRetry = (): void => {
    this.setState({ hasError: false, error: null });
  };

  override render(): ReactNode {
    if (this.state.hasError) {
      if (this.props.fallback) {
        return this.props.fallback;
      }

      const strings = pickStrings();
      return (
        <div role="alert">
          <h2>{strings.title}</h2>
          <p>{this.state.error?.message}</p>
          <button type="button" onClick={this.handleRetry}>
            {strings.retry}
          </button>
        </div>
      );
    }

    return this.props.children;
  }
}
