import {
  Suspense,
  lazy,
  type ComponentType,
  Component,
  type ErrorInfo,
} from 'react';
import { LoadingSpinner } from './loading-spinner';
import { logger } from '@/utils/logger';
import { Button } from './button';
import { AlertTriangle, RefreshCw } from 'lucide-react';

// CRITIQUE FIX #16: Composant de fallback amélioré pour les erreurs de chargement lazy
function LazyErrorFallback({
  pageName,
  error,
  onRetry,
}: {
  pageName: string;
  error?: Error;
  onRetry?: () => void;
}) {
  return (
    <div className="flex flex-col items-center justify-center min-h-[50vh] p-8 text-center animate-in fade-in zoom-in duration-300">
      <div className="bg-kodo-ink/50 border border-kodo-steel/30 rounded-xl p-8 max-w-md w-full shadow-lg backdrop-blur-sm">
        <div className="w-16 h-16 bg-kodo-red/10 rounded-full flex items-center justify-center mx-auto mb-6">
          <AlertTriangle className="h-8 w-8 text-kodo-red" />
        </div>

        <h2 className="text-xl font-bold mb-2">Failed to load {pageName}</h2>
        <p className="text-kodo-content-dim mb-6 text-sm">
          {(() => {
            try {
              if (!error) return 'Currently unable to access this component. Please check your connection.';
              if (typeof error === 'string') return error;
              if (error instanceof Error) return error.message;
              return String(error);
            } catch (e) {
              return 'An unknown error occurred.';
            }
          })()}
        </p>

        <div className="flex flex-col gap-3">
          {onRetry && (
            <Button
              onClick={onRetry}
              variant="outline"
              className="w-full flex items-center justify-center gap-2"
            >
              <RefreshCw className="h-4 w-4" />
              Try Again
            </Button>
          )}
          <Button
            onClick={() => window.location.reload()}
            variant="default"
            className="w-full flex items-center justify-center gap-2"
          >
            Refresh Page
          </Button>
        </div>
      </div>
    </div>
  );
}

// CRITIQUE FIX #16: ErrorBoundary spécifique pour les composants lazy
class LazyErrorBoundary extends Component<
  {
    children: React.ReactNode;
    pageName: string;
    onError?: (error: Error, errorInfo: ErrorInfo) => void;
  },
  { hasError: boolean; error?: Error }
> {
  constructor(props: {
    children: React.ReactNode;
    pageName: string;
    onError?: (error: Error, errorInfo: ErrorInfo) => void;
  }) {
    super(props);
    this.state = { hasError: false };
  }

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

  override componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    // CRITIQUE FIX #16: Logger l'erreur avec le logger centralisé au lieu de console.error
    logger.error('[LazyComponent] Failed to load lazy component', {
      pageName: this.props.pageName,
      error: error instanceof Error ? error.message : String(error),
      stack: error instanceof Error ? error.stack : undefined,
      componentStack: errorInfo.componentStack,
    });

    if (this.props.onError) {
      this.props.onError(error, errorInfo);
    }
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: undefined });
  };

  override render() {
    if (this.state.hasError) {
      return (
        <LazyErrorFallback
          pageName={this.props.pageName}
          error={this.state.error}
          onRetry={this.handleRetry}
        />
      );
    }

    return this.props.children;
  }
}

/**
 * LazyComponentProps - Propriétés pour les composants lazy créés
 *
 * @interface LazyComponentProps
 */
interface LazyComponentProps {
  /**
    * Composant de fallback personnalisé à afficher pendant le chargement
    * Si non fourni, utilise LoadingSpinner par défaut
    */
  fallback?: React.ReactNode;
}

/**
 * createLazyComponent - Factory pour créer des composants lazy avec Suspense
 *
 * Crée un composant lazy avec gestion automatique du Suspense et du fallback.
 * Utile pour le code splitting et le chargement à la demande des composants.
 *
 * @template T - Type du composant à charger
 * @param {() => Promise<{ default: T }>} importFunc - Fonction d'import dynamique
 * @param {React.ReactNode} fallback - Composant de fallback (optionnel)
 * @returns {ComponentType} Composant wrapper avec Suspense intégré
 *
 * @example
 * ```tsx
 * // Créer un composant lazy
 * const LazyDashboard = createLazyComponent(
 *   () => import('@/pages/DashboardPage').then(m => ({ default: m.DashboardPage }))
 * );
 *
 * // Utiliser le composant lazy
 * <LazyDashboard fallback={<CustomLoader />} />
 * ```
 *
 * @function
 */
// CRITIQUE FIX #16: Wrapper pour gérer les erreurs de chargement lazy de manière standardisée
// CRITIQUE FIX #16: Wrapper pour gérer les erreurs de chargement lazy de manière standardisée
function createLazyWithErrorHandling<T extends ComponentType<any>>(
  importFunc: () => Promise<{ default: T } | T>, // Allow direct component return if needed
  pageName: string,
) {
  return importFunc()
    .then((module) => {
      // Handle both default exports and named exports (if the named export matches the module structure)
      // This is a safety check: if 'default' exists, usage is correct.
      // If 'default' is missing but we have a module object, we might need to find the component.
      // For consistent usage with React.lazy, we usually expect { default: Component }.

      // However, if the user does named imports in the lambda:
      // () => import('...').then(m => ({ default: m.NamedComponent }))
      // That is ALREADY handled by the lambda itself returning the correct shape.

      // This catch is mainly for network errors during fetch.
      return module as { default: T };
    })
    .catch((err) => {
      // CRITIQUE FIX #16: Logger l'erreur avec le logger centralisé
      const errorMessage = err instanceof Error ? err.message : String(err);
      logger.error('[LazyComponent] Failed to import lazy component', {
        pageName,
        error: errorMessage,
        stack: err instanceof Error ? err.stack : undefined,
      });

      // Retourner un composant d'erreur au lieu de laisser l'erreur se propager
      return Promise.resolve({
        default: () => (
          <LazyErrorFallback
            pageName={pageName}
            error={err instanceof Error ? err : new Error(errorMessage)}
          />
        ),
      }) as unknown as Promise<{ default: T }>;
    });
}

export function createLazyComponent<T extends ComponentType<any>>(
  importFunc: () => Promise<any>,
  fallback?: React.ReactNode,
  pageName?: string,
) {
  // CRITIQUE FIX #16: Utiliser la fonction avec gestion d'erreur si pageName est fourni
  const safeImportFunc = pageName
    ? () => createLazyWithErrorHandling(importFunc as any, pageName)
    : importFunc;

  const LazyComponent = lazy(safeImportFunc);

  return function WrappedLazyComponent(
    props: React.ComponentProps<T> & LazyComponentProps,
  ) {
    // Extraire fallback des props pour ne pas le passer au composant lazy
    const { fallback: _fallback, ...componentProps } = props;

    // CRITIQUE FIX #16: Wrapper avec ErrorBoundary pour capturer les erreurs runtime
    const component = (
      <Suspense fallback={fallback || <LoadingSpinner />}>
        {/* LazyComponent props are compatible but TypeScript can't infer it */}
        <LazyComponent {...componentProps} />
      </Suspense>
    );

    // Si pageName est fourni, wrapper avec LazyErrorBoundary
    if (pageName) {
      return (
        <LazyErrorBoundary pageName={pageName}>{component}</LazyErrorBoundary>
      );
    }

    return component;
  };
}

// Composants lazy communs
// CRITIQUE FIX #16: Ajouter pageName pour tous les composants lazy pour une meilleure gestion d'erreur
export const LazyDashboard = createLazyComponent(
  () => import('@/features/dashboard/pages/DashboardPage'), // Default export usage
  undefined,
  'Dashboard',
);
export const LazyChat = createLazyComponent(
  () =>
    import('@/features/chat/pages/ChatPage').then((m) => ({
      default: m.ChatPage,
    })),
  undefined,
  'Chat',
);
export const LazyLibrary = createLazyComponent(
  () =>
    import('@/features/library/pages/LibraryPage').then((m) => ({
      default: m.LibraryPage,
    })),
  undefined,
  'Library',
);
export const LazyProfile = createLazyComponent(
  () =>
    import('@/features/profile/pages/UserProfilePage').then((m) => ({
      default: m.UserProfilePage,
    })),
  undefined,
  'Profile',
);
export const LazySettings = createLazyComponent(
  () =>
    import('@/features/settings/pages/SettingsPage').then((m) => ({
      default: m.SettingsPage,
    })),
  undefined,
  'Settings',
);
export const LazyLogin = createLazyComponent(
  () => import('@/features/auth/pages/LoginPage'),
  undefined,
  'Login',
);
export const LazyRegister = createLazyComponent(
  () => import('@/features/auth/pages/RegisterPage'),
  undefined,
  'Register',
);
export const LazyForgotPassword = createLazyComponent(
  () => import('@/features/auth/pages/ForgotPasswordPage'),
  undefined,
  'Forgot Password',
);
export const LazyVerifyEmail = createLazyComponent(
  () => import('@/features/auth/pages/VerifyEmailPage'),
  undefined,
  'Verify Email',
);
export const LazyResetPassword = createLazyComponent(
  () => import('@/features/auth/pages/ResetPasswordPage'),
  undefined,
  'Reset Password',
);
export const LazySessions = createLazyComponent(
  () => import('@/features/auth/pages/SessionsPage'),
  undefined,
  'Sessions',
);
export const LazyNotFound = createLazyComponent(
  () => import('@/features/error/pages/NotFoundPage'),
  undefined,
  'Not Found',
);
export const LazyServerError = createLazyComponent(
  () => import('@/features/error/pages/ServerErrorPage'),
  undefined,
  'Server Error',
);
export const LazyUserProfile = createLazyComponent(
  () =>
    import('@/features/profile/pages/UserProfilePage').then((m) => ({
      default: m.UserProfilePage,
    })),
  undefined,
  'User Profile',
);
export const LazyRoles = createLazyComponent(
  () =>
    import('@/features/roles/pages/RolesPage').then((m) => ({
      default: m.RolesPage,
    })),
  undefined,
  'Roles',
);
export const LazyTrackDetail = createLazyComponent(
  () =>
    import('@/features/tracks/pages/TrackDetailPage').then((m) => ({
      default: m.TrackDetailPage,
    })),
  undefined,
  'Track Detail',
);
export const LazyPlaylistRoutes = createLazyComponent(
  () =>
    import('@/features/playlists/routes').then((m) => ({
      default: m.PlaylistRoutes,
    })),
  undefined,
  'Playlists',
);

export const LazyAdminDashboard = createLazyComponent(
  () =>
    import('@/components/admin/AdminDashboardView').then((m) => ({
      default: m.AdminDashboardView,
    })),
  undefined,
  'Admin Dashboard',
);

export const LazyAnalytics = createLazyComponent(
  () =>
    import('@/components/views/AnalyticsView').then((m) => ({
      default: m.AnalyticsView,
    })),
  undefined,
  'Analytics',
);

export const LazyWebhooks = createLazyComponent(
  () =>
    import('@/components/developer/WebhooksView').then((m) => ({
      default: m.WebhooksView,
    })),
  undefined,
  'Webhooks',
);

export const LazyDesignSystemDemo = createLazyComponent(
  () =>
    import('@/components/demo/DesignSystemDemo').then((m) => ({
      default: m.DesignSystemDemo,
    })),
  undefined,
  'Design System Demo',
);

export const LazySocial = createLazyComponent(
  () =>
    import('@/components/views/SocialView').then((m) => ({
      default: m.SocialView,
    })),
  undefined,
  'Social',
);

export const LazyGear = createLazyComponent(
  () =>
    import('@/components/views/GearView').then((m) => ({
      default: m.GearView,
    })),
  undefined,
  'Gear',
);

export const LazyLive = createLazyComponent(
  () =>
    import('@/components/views/LiveView').then((m) => ({
      default: m.LiveView,
    })),
  undefined,
  'Live',
);

export const LazyEducation = createLazyComponent(
  () =>
    import('@/components/views/EducationView').then((m) => ({
      default: m.EducationView,
    })),
  undefined,
  'Education',
);

export const LazyQueue = createLazyComponent(
  () =>
    import('@/components/library/playlists/QueueView').then((m) => ({
      default: m.QueueView,
    })),
  undefined,
  'Queue',
);

export const LazyDeveloper = createLazyComponent(
  () =>
    import('@/components/developer/DeveloperDashboardView').then((m) => ({
      default: m.DeveloperDashboardView,
    })),
  undefined,
  'Developer',
);

export const LazyNotifications = createLazyComponent(
  () =>
    import('@/components/views/NotificationsView').then((m) => ({
      default: m.NotificationsView,
    })),
  undefined,
  'Notifications',
);

export const LazyMarketplace = createLazyComponent(
  () =>
    import('@/pages/marketplace/MarketplaceHome').then((m) => ({
      default: m.MarketplaceHome,
    })),
  undefined,
  'Marketplace',
);

export const LazySearch = createLazyComponent(
  () =>
    import('@/features/search/pages/SearchPage').then((m) => ({
      default: m.SearchPage,
    })),
  undefined,
  'Search',
);






// New pages for navigation fix







export const LazySellerDashboard = createLazyComponent(
  () =>
    import('@/components/seller/SellerDashboardView').then((m) => ({
      default: m.SellerDashboardView,
    })),
  undefined,
  'Seller Dashboard',
);

export const LazyWishlist = createLazyComponent(
  () =>
    import('@/components/commerce/WishlistView').then((m) => ({
      default: m.WishlistView,
    })),
  undefined,
  'Wishlist',
);

export const LazyPurchases = createLazyComponent(
  () =>
    import('@/components/views/PurchasesView').then((m) => ({
      default: m.PurchasesView,
    })),
  undefined,
  'Purchases',
);
