import React, { useState, useCallback, forwardRef } from 'react';
import { clsx } from 'clsx';
import { useTheme } from '../../../contexts/ThemeContext';
import { useHasAccess } from '../../../hooks/useAccessControl';
import { Header } from '../Header';
import { Sidebar } from '../Sidebar';
import { Footer } from '../Footer';
import { DemoBanner } from '../DemoBanner';

export interface AppShellProps {
  children: React.ReactNode;
  className?: string;
  /**
   * Control sidebar visibility
   */
  showSidebar?: boolean;
  /**
   * Control header visibility
   */
  showHeader?: boolean;
  /**
   * Control footer visibility
   */
  showFooter?: boolean;
  /**
   * Make the layout fullscreen (hide header and footer)
   */
  fullScreen?: boolean;
  /**
   * Add padding to the main content area
   */
  padded?: boolean;
  /**
   * Initial sidebar collapsed state
   */
  initialSidebarCollapsed?: boolean;
  /**
   * Custom loading component
   */
  loadingComponent?: React.ReactNode;
  /**
   * Custom error boundary
   */
  errorBoundary?: React.ComponentType<{ children: React.ReactNode; error?: Error }>;
}

export interface AppShellRef {
  toggleSidebar: () => void;
  collapseSidebar: () => void;
  expandSidebar: () => void;
  isSidebarOpen: boolean;
  isSidebarCollapsed: boolean;
}

/**
 * AppShell - Main application shell that combines header, sidebar, and main content area
 * 
 * Features:
 * - Responsive layout with collapsible sidebar
 * - Mobile-friendly with drawer overlay
 * - Content area that adjusts to sidebar state
 * - Supports fullscreen mode for special pages
 * - Integrated with authentication and theming
 */
export const AppShell = forwardRef<AppShellRef, AppShellProps>(({
  children,
  className,
  showSidebar = true,
  showHeader = true,
  showFooter = true,
  fullScreen = false,
  padded = true,
  initialSidebarCollapsed = false,
  loadingComponent,
  errorBoundary: ErrorBoundary,
}, ref) => {
  const authLoading = false; // Since we're in a protected route, auth loading should be false
  const { resolvedTheme } = useTheme();
  const hasAccess = useHasAccess(); // Check both authentication and demo mode

  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(initialSidebarCollapsed);
  const [error, setError] = useState<Error | null>(null);

  // Sidebar control functions
  const toggleSidebar = useCallback(() => {
    if (window.innerWidth < 1024) {
      // Mobile: toggle drawer
      setIsSidebarOpen(prev => !prev);
    } else {
      // Desktop: toggle collapsed state
      setIsSidebarCollapsed(prev => !prev);
    }
  }, []);

  const collapseSidebar = useCallback(() => {
    if (window.innerWidth < 1024) {
      setIsSidebarOpen(false);
    } else {
      setIsSidebarCollapsed(true);
    }
  }, []);

  const expandSidebar = useCallback(() => {
    if (window.innerWidth < 1024) {
      setIsSidebarOpen(true);
    } else {
      setIsSidebarCollapsed(false);
    }
  }, []);

  // Close mobile sidebar when clicking outside
  const handleOverlayClick = useCallback(() => {
    if (window.innerWidth < 1024) {
      setIsSidebarOpen(false);
    }
  }, []);

  // Expose ref methods
  React.useImperativeHandle(ref, () => ({
    toggleSidebar,
    collapseSidebar,
    expandSidebar,
    isSidebarOpen,
    isSidebarCollapsed,
  }), [toggleSidebar, collapseSidebar, expandSidebar, isSidebarOpen, isSidebarCollapsed]);

  // Handle responsive sidebar state and prevent body scroll on mobile
  React.useEffect(() => {
    const handleResize = () => {
      if (window.innerWidth >= 1024) {
        // Desktop: close mobile drawer
        setIsSidebarOpen(false);
      }
    };

    // Prevent body scroll when mobile sidebar is open
    if (isSidebarOpen && window.innerWidth < 1024) {
      document.body.style.overflow = 'hidden';
      document.body.style.position = 'fixed';
      document.body.style.width = '100%';
    } else {
      document.body.style.overflow = '';
      document.body.style.position = '';
      document.body.style.width = '';
    }

    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
      // Cleanup on unmount
      document.body.style.overflow = '';
      document.body.style.position = '';
      document.body.style.width = '';
    };
  }, [isSidebarOpen]);

  // Error boundary handling
  React.useEffect(() => {
    const handleError = (event: ErrorEvent) => {
      setError(new Error(event.message));
    };

    const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
      setError(new Error(event.reason?.message || 'Promise rejection'));
    };

    window.addEventListener('error', handleError);
    window.addEventListener('unhandledrejection', handleUnhandledRejection);

    return () => {
      window.removeEventListener('error', handleError);
      window.removeEventListener('unhandledrejection', handleUnhandledRejection);
    };
  }, []);

  // Show loading state
  if (authLoading) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-[var(--bg-primary)]">
        {loadingComponent || (
          <div className="flex flex-col items-center gap-4">
            <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[var(--color-primary)]"></div>
            <p className="text-[var(--text-secondary)]">Cargando aplicación...</p>
          </div>
        )}
      </div>
    );
  }

  // Show error state
  if (error && ErrorBoundary) {
    return <ErrorBoundary error={error}>{children}</ErrorBoundary>;
  }

  const shouldShowSidebar = showSidebar && hasAccess && !fullScreen;
  const shouldShowHeader = showHeader && !fullScreen;
  const shouldShowFooter = showFooter && !fullScreen;

  return (
    <div
      className={clsx(
        'min-h-screen bg-[var(--bg-primary)] flex flex-col',
        resolvedTheme,
        className
      )}
      data-testid="app-shell"
    >
      {/* Header */}
      {shouldShowHeader && (
        <Header
            onMenuClick={toggleSidebar}
            sidebarCollapsed={isSidebarCollapsed}
            className="z-[var(--z-fixed)]"
          />
      )}

      {/* Demo Banner - appears below header */}
      <DemoBanner />

      <div className="flex flex-1 relative">
        {/* Sidebar */}
        {shouldShowSidebar && (
          <>
            <Sidebar
              isOpen={isSidebarOpen}
              isCollapsed={isSidebarCollapsed}
              onClose={() => setIsSidebarOpen(false)}
              onToggleCollapse={toggleSidebar}
              className="z-[var(--z-fixed)]"
            />
            
            {/* Mobile overlay */}
            {isSidebarOpen && (
              <div
                className="fixed inset-0 bg-black/50 z-[var(--z-modal-backdrop)] lg:hidden backdrop-blur-sm"
                onClick={handleOverlayClick}
                onTouchStart={handleOverlayClick}
                aria-hidden="true"
              />
            )}
          </>
        )}

        {/* Main content */}
        <main
          className={clsx(
            'flex-1 flex flex-col transition-all duration-300 ease-in-out',
            'overflow-x-hidden', // Prevent horizontal overflow
            // Add header offset
            shouldShowHeader && 'pt-[var(--header-height)]',
            // Adjust margins based on sidebar state
            shouldShowSidebar && hasAccess && !isSidebarCollapsed && 'lg:ml-[var(--sidebar-width)]',
            shouldShowSidebar && hasAccess && isSidebarCollapsed && 'lg:ml-[var(--sidebar-collapsed-width)]',
            // Add padding to content
            padded && 'px-4 lg:px-6 pb-4 lg:pb-6'
          )}
          role="main"
          aria-label="Contenido principal"
        >
          {children}
        </main>
      </div>

      {/* Footer */}
      {shouldShowFooter && (
        <Footer
          compact={true}
          showPrivacyLinks={true}
          className={clsx(
            'transition-all duration-300 ease-in-out',
            shouldShowSidebar && hasAccess && !isSidebarCollapsed && 'lg:ml-[var(--sidebar-width)]',
            shouldShowSidebar && hasAccess && isSidebarCollapsed && 'lg:ml-[var(--sidebar-collapsed-width)]'
          )}
        />
      )}
    </div>
  );
});

AppShell.displayName = 'AppShell';