import React, { Suspense, lazy, Component, ReactNode } from 'react';
import { Loader2 } from 'lucide-react';

// ── Error Boundary ──────────────────────────────────────────────────────

interface PluginErrorBoundaryProps {
  children: ReactNode;
  pluginName: string;
}

interface PluginErrorBoundaryState {
  hasError: boolean;
}

class PluginErrorBoundary extends Component<PluginErrorBoundaryProps, PluginErrorBoundaryState> {
  state = { hasError: false };

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

  render() {
    if (this.state.hasError) {
      return (
        <div className="p-4 text-sm text-red-600" role="alert">
          Failed to load plugin: {this.props.pluginName}
        </div>
      );
    }
    return this.props.children;
  }
}

// ── Lazy Component Cache ────────────────────────────────────────────────

const componentCache = new Map<string, React.LazyExoticComponent<React.ComponentType<any>>>();

function getLazyComponent(componentPath: string): React.LazyExoticComponent<React.ComponentType<any>> {
  if (componentCache.has(componentPath)) {
    return componentCache.get(componentPath)!;
  }

  // Convert @/pages/Mail to ../pages/Mail for dynamic import
  const importPath = componentPath.replace(/^@\//, '../');

  const LazyComp = lazy(() =>
    import(/* @vite-ignore */ importPath).then((m) => ({
      default: m.default || m[Object.keys(m)[0]],
    }))
  );

  componentCache.set(componentPath, LazyComp);
  return LazyComp;
}

// ── PluginPage Component ───────────────────────────────────────────────

interface PluginPageProps {
  component: string;
  pluginName: string;
}

/**
 * PluginPage — dynamically loads a plugin page component using React.lazy().
 * Wraps the lazy component in Suspense with a centered spinner fallback
 * and an ErrorBoundary that shows a fallback message on failure.
 */
export function PluginPage({ component, pluginName }: PluginPageProps) {
  const LazyComp = getLazyComponent(component);

  return (
    <PluginErrorBoundary pluginName={pluginName}>
      <Suspense
        fallback={
          <div className="flex items-center justify-center min-h-[50vh]">
            <Loader2 className="animate-spin h-8 w-8 text-primary-500" />
          </div>
        }
      >
        <LazyComp />
      </Suspense>
    </PluginErrorBoundary>
  );
}
