import React, { useState, useCallback, forwardRef, useMemo } from 'react';
import { clsx } from 'clsx';
import { useLocation, useNavigate } from 'react-router-dom';
import { useAuthUser, useIsAuthenticated } from '../../../stores';
import { useCurrentTenantAccess } from '../../../stores/tenant.store';
import { getNavigationRoutes, canAccessRoute, ROUTES } from '../../../router/routes.config';
import { useSubscriptionAwareRoutes } from '../../../hooks/useSubscriptionAwareRoutes';
import { Button } from '../../ui';
import { Badge } from '../../ui';
import { Tooltip } from '../../ui';
import {
  LayoutDashboard,
  Package,
  Factory,
  BarChart3,
  Brain,
  ShoppingCart,
  Truck,
  Zap,
  Database,
  Store,
  GraduationCap,
  Bell,
  Settings,
  User,
  CreditCard,
  ChevronLeft,
  ChevronRight,
  ChevronDown,
  Dot,
  Menu
} from 'lucide-react';

export interface SidebarProps {
  className?: string;
  /**
   * Whether the sidebar is open (mobile drawer state)
   */
  isOpen?: boolean;
  /**
   * Whether the sidebar is collapsed (desktop state)
   */
  isCollapsed?: boolean;
  /**
   * Callback when sidebar is closed (mobile)
   */
  onClose?: () => void;
  /**
   * Callback when sidebar collapse state is toggled (desktop)
   */
  onToggleCollapse?: () => void;
  /**
   * Custom navigation items
   */
  customItems?: NavigationItem[];
  /**
   * Show/hide collapse button
   */
  showCollapseButton?: boolean;
  /**
   * Show/hide footer
   */
  showFooter?: boolean;
}

export interface NavigationItem {
  id: string;
  label: string;
  path: string;
  icon?: React.ComponentType<{ className?: string }>;
  badge?: {
    text: string;
    variant?: 'default' | 'primary' | 'success' | 'warning' | 'error';
  };
  children?: NavigationItem[];
  requiredPermissions?: string[];
  requiredRoles?: string[];
  disabled?: boolean;
  external?: boolean;
}

export interface SidebarRef {
  scrollToItem: (path: string) => void;
  expandItem: (path: string) => void;
  collapseItem: (path: string) => void;
}

const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
  dashboard: LayoutDashboard,
  inventory: Package,
  production: Factory,
  sales: BarChart3,
  forecasting: Brain,
  orders: ShoppingCart,
  procurement: Truck,
  pos: Zap,
  data: Database,
  database: Store,
  training: GraduationCap,
  notifications: Bell,
  settings: Settings,
  user: User,
  'credit-card': CreditCard,
};

/**
 * Sidebar - Navigation sidebar with collapsible menu items and role-based access
 * 
 * Features:
 * - Hierarchical navigation menu with icons
 * - Icons for menu items with fallback support
 * - Collapsible sections with smooth animations
 * - Active state highlighting with proper contrast
 * - Role-based menu filtering and permissions
 * - Responsive design with mobile drawer mode
 * - Keyboard navigation support
 * - Smooth scrolling to items
 * - Badge support for notifications/counts
 */
export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
  className,
  isOpen = false,
  isCollapsed = false,
  onClose,
  onToggleCollapse,
  customItems,
  showCollapseButton = true,
  showFooter = true,
}, ref) => {
  const location = useLocation();
  const navigate = useNavigate();
  const user = useAuthUser();
  const isAuthenticated = useIsAuthenticated();
  const currentTenantAccess = useCurrentTenantAccess();
  
  const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
  const [hoveredItem, setHoveredItem] = useState<string | null>(null);
  const sidebarRef = React.useRef<HTMLDivElement>(null);

  // Get subscription-aware navigation routes
  const baseNavigationRoutes = useMemo(() => getNavigationRoutes(), []);
  const { filteredRoutes: subscriptionFilteredRoutes } = useSubscriptionAwareRoutes(baseNavigationRoutes);

  // Convert routes to navigation items - memoized
  const navigationItems = useMemo(() => {
    const convertRoutesToItems = (routes: typeof subscriptionFilteredRoutes): NavigationItem[] => {
      return routes.map(route => ({
        id: route.path,
        label: route.title,
        path: route.path,
        icon: route.icon ? iconMap[route.icon] : undefined,
        requiredPermissions: route.requiredPermissions,
        requiredRoles: route.requiredRoles,
        children: route.children ? convertRoutesToItems(route.children) : undefined,
      }));
    };

    return customItems || convertRoutesToItems(subscriptionFilteredRoutes);
  }, [customItems, subscriptionFilteredRoutes]);

  // Filter items based on user permissions - memoized to prevent infinite re-renders
  const visibleItems = useMemo(() => {
    const filterItemsByPermissions = (items: NavigationItem[]): NavigationItem[] => {
      if (!isAuthenticated || !user) return [];

      return items.map(item => ({
        ...item, // Create a shallow copy to avoid mutation
        children: item.children ? filterItemsByPermissions(item.children) : item.children
      })).filter(item => {
        // Combine global and tenant roles for comprehensive access control
        const globalUserRoles = user.role ? [user.role as string] : [];
        const tenantRole = currentTenantAccess?.role;
        const tenantRoles = tenantRole ? [tenantRole as string] : [];
        const allUserRoles = [...globalUserRoles, ...tenantRoles];
        const tenantPermissions = currentTenantAccess?.permissions || [];

        const hasAccess = !item.requiredPermissions && !item.requiredRoles || 
          canAccessRoute(
            { 
              path: item.path, 
              requiredRoles: item.requiredRoles, 
              requiredPermissions: item.requiredPermissions 
            } as any,
            isAuthenticated,
            allUserRoles,
            tenantPermissions
          );

        return hasAccess;
      });
    };

    return filterItemsByPermissions(navigationItems);
  }, [navigationItems, isAuthenticated, user, currentTenantAccess]);

  // Handle item click
  const handleItemClick = useCallback((item: NavigationItem) => {
    if (item.disabled) return;

    if (item.children && item.children.length > 0) {
      // Toggle expansion for parent items
      setExpandedItems(prev => {
        const newSet = new Set(prev);
        if (newSet.has(item.id)) {
          newSet.delete(item.id);
        } else {
          newSet.add(item.id);
        }
        return newSet;
      });
    } else {
      // Navigate to item
      if (item.external) {
        window.open(item.path, '_blank');
      } else {
        navigate(item.path);
        if (onClose) onClose(); // Close mobile drawer
      }
    }
  }, [navigate, onClose]);

  // Scroll to item
  const scrollToItem = useCallback((path: string) => {
    const element = sidebarRef.current?.querySelector(`[data-path="${path}"]`);
    if (element) {
      element.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  }, []);

  // Expand item
  const expandItem = useCallback((path: string) => {
    setExpandedItems(prev => new Set(prev).add(path));
  }, []);

  // Collapse item
  const collapseItem = useCallback((path: string) => {
    setExpandedItems(prev => {
      const newSet = new Set(prev);
      newSet.delete(path);
      return newSet;
    });
  }, []);

  // Auto-expand parent items for active path
  const findParentPaths = useCallback((items: NavigationItem[], targetPath: string, parents: string[] = []): string[] => {
    for (const item of items) {
      const currentPath = [...parents, item.id];
      
      if (item.path === targetPath) {
        return parents;
      }
      
      if (item.children) {
        const found = findParentPaths(item.children, targetPath, currentPath);
        if (found.length > 0) {
          return found;
        }
      }
    }
    return [];
  }, []);

  React.useEffect(() => {
    const parentPaths = findParentPaths(visibleItems, location.pathname);
    if (parentPaths.length > 0) {
      setExpandedItems(prev => new Set([...prev, ...parentPaths]));
    }
  }, [location.pathname, findParentPaths, visibleItems]);

  // Expose ref methods
  React.useImperativeHandle(ref, () => ({
    scrollToItem,
    expandItem,
    collapseItem,
  }), [scrollToItem, expandItem, collapseItem]);

  // Handle keyboard navigation and touch gestures
  React.useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && isOpen && onClose) {
        onClose();
      }
    };

    let touchStartX = 0;
    let touchStartY = 0;
    
    const handleTouchStart = (e: TouchEvent) => {
      if (isOpen) {
        touchStartX = e.touches[0].clientX;
        touchStartY = e.touches[0].clientY;
      }
    };

    const handleTouchMove = (e: TouchEvent) => {
      if (!isOpen || !onClose) return;
      
      const touchCurrentX = e.touches[0].clientX;
      const touchCurrentY = e.touches[0].clientY;
      const deltaX = touchStartX - touchCurrentX;
      const deltaY = Math.abs(touchStartY - touchCurrentY);
      
      // Only trigger swipe left to close if it's more horizontal than vertical
      // and the swipe distance is significant
      if (deltaX > 50 && deltaX > deltaY * 2) {
        onClose();
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('touchstart', handleTouchStart, { passive: true });
    document.addEventListener('touchmove', handleTouchMove, { passive: true });
    
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      document.removeEventListener('touchstart', handleTouchStart);
      document.removeEventListener('touchmove', handleTouchMove);
    };
  }, [isOpen, onClose]);

  // Render submenu overlay for collapsed sidebar
  const renderSubmenuOverlay = (item: NavigationItem) => {
    if (!item.children || item.children.length === 0) return null;

    return (
      <div className="fixed left-[var(--sidebar-collapsed-width)] top-0 z-[var(--z-popover)] min-w-[200px] bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-lg shadow-lg py-2">
        <div className="px-3 py-2 border-b border-[var(--border-primary)]">
          <span className="text-sm font-medium text-[var(--text-secondary)]">
            {item.label}
          </span>
        </div>
        <ul className="py-1">
          {item.children.map(child => (
            <li key={child.id}>
              <button
                onClick={() => handleItemClick(child)}
                disabled={child.disabled}
                className={clsx(
                  'w-full text-left px-3 py-2 text-sm transition-colors duration-200',
                  'hover:bg-[var(--bg-secondary)]',
                  location.pathname === child.path && 'bg-[var(--color-primary)]/10 text-[var(--color-primary)] border-r-2 border-[var(--color-primary)]',
                  child.disabled && 'opacity-50 cursor-not-allowed'
                )}
              >
                <div className="flex items-center">
                  {child.icon && (
                    <child.icon className="w-4 h-4 mr-3 flex-shrink-0" />
                  )}
                  <span className="truncate">{child.label}</span>
                  {child.badge && (
                    <Badge
                      variant={child.badge.variant || 'default'}
                      size="sm"
                      className="ml-2 text-xs"
                    >
                      {child.badge.text}
                    </Badge>
                  )}
                </div>
              </button>
            </li>
          ))}
        </ul>
      </div>
    );
  };

  // Render navigation item
  const renderItem = (item: NavigationItem, level = 0) => {
    const isActive = location.pathname === item.path || location.pathname.startsWith(item.path + '/');
    const isExpanded = expandedItems.has(item.id);
    const hasChildren = item.children && item.children.length > 0;
    const isHovered = hoveredItem === item.id;
    const ItemIcon = item.icon;

    const itemContent = (
      <div
        className={clsx(
          'flex items-center w-full text-left transition-colors duration-200',
          'group relative',
          level > 0 && 'pl-6',
        )}
      >
        <div className="relative">
          {ItemIcon && (
            <ItemIcon 
              className={clsx(
                'flex-shrink-0 transition-colors duration-200',
                isCollapsed ? 'w-5 h-5' : 'w-4 h-4 mr-3',
                isActive 
                  ? 'text-[var(--color-primary)]' 
                  : 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'
              )} 
            />
          )}
          
          {/* Submenu indicator for collapsed sidebar */}
          {isCollapsed && hasChildren && level === 0 && (
            <div className="absolute -bottom-1 -right-1 w-2 h-2 bg-[var(--color-primary)] rounded-full opacity-75" />
          )}
        </div>
        
        {!ItemIcon && level > 0 && (
          <Dot className={clsx(
            'flex-shrink-0 w-4 h-4 mr-3 transition-colors duration-200',
            isActive 
              ? 'text-[var(--color-primary)]' 
              : 'text-[var(--text-tertiary)]'
          )} />
        )}

        {(!isCollapsed || level > 0) && (
          <>
            <span className={clsx(
              'flex-1 truncate transition-colors duration-200 text-sm font-medium',
              isActive 
                ? 'text-[var(--color-primary)]' 
                : 'text-[var(--text-primary)] group-hover:text-[var(--text-primary)]'
            )}>
              {item.label}
            </span>

            {item.badge && (
              <Badge
                variant={item.badge.variant || 'default'}
                size="sm"
                className="ml-2 text-xs"
              >
                {item.badge.text}
              </Badge>
            )}

            {hasChildren && (
              <ChevronDown className={clsx(
                'flex-shrink-0 w-4 h-4 ml-2 transition-transform duration-200',
                isExpanded && 'transform rotate-180',
                isActive 
                  ? 'text-[var(--color-primary)]' 
                  : 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'
              )} />
            )}
          </>
        )}
      </div>
    );

    const button = (
      <div className="relative">
        <button
          onClick={() => handleItemClick(item)}
          disabled={item.disabled}
          data-path={item.path}
          onMouseEnter={() => {
            if (isCollapsed && hasChildren && level === 0) {
              setHoveredItem(item.id);
            }
          }}
          onMouseLeave={() => {
            if (isCollapsed && hasChildren && level === 0) {
              setHoveredItem(null);
            }
          }}
          className={clsx(
            'w-full rounded-lg transition-all duration-200',
            'focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]/20',
            isActive && 'bg-[var(--color-primary)]/10 border-l-2 border-[var(--color-primary)]',
            !isActive && 'hover:bg-[var(--bg-secondary)]',
            item.disabled && 'opacity-50 cursor-not-allowed',
            isCollapsed && !hasChildren ? 'flex justify-center items-center p-2 mx-1' : 'p-3'
          )}
          aria-expanded={hasChildren ? isExpanded : undefined}
          aria-current={isActive ? 'page' : undefined}
          title={isCollapsed ? item.label : undefined}
        >
          {itemContent}
        </button>
        
        {/* Submenu overlay for collapsed sidebar */}
        {isCollapsed && hasChildren && level === 0 && isHovered && (
          <div 
            className="absolute left-full top-0 ml-2 z-[var(--z-popover)]"
            onMouseEnter={() => setHoveredItem(item.id)}
            onMouseLeave={() => setHoveredItem(null)}
          >
            {renderSubmenuOverlay(item)}
          </div>
        )}
      </div>
    );

    return (
      <li key={item.id} className="relative">
        {isCollapsed && !hasChildren && ItemIcon ? (
          <Tooltip content={item.label} side="right">
            {button}
          </Tooltip>
        ) : (
          button
        )}

        {hasChildren && isExpanded && (!isCollapsed || level > 0) && (
          <ul className="mt-1 space-y-1 pl-4">
            {item.children?.map(child => renderItem(child, level + 1))}
          </ul>
        )}
      </li>
    );
  };

  if (!isAuthenticated) {
    return null;
  }

  return (
    <>
      {/* Desktop Sidebar */}
      <aside
        ref={sidebarRef}
        className={clsx(
          'fixed left-0 top-[var(--header-height)] bottom-0',
          'bg-[var(--bg-primary)] border-r border-[var(--border-primary)]',
          'transition-all duration-300 ease-in-out z-[var(--z-fixed)]',
          'hidden lg:flex lg:flex-col',
          isCollapsed ? 'w-[var(--sidebar-collapsed-width)]' : 'w-[var(--sidebar-width)]',
          className
        )}
        aria-label="Navegación principal"
      >
        {/* Navigation */}
        <nav className={clsx('flex-1 overflow-y-auto', isCollapsed ? 'px-1 py-4' : 'p-4')}>
          <ul className={clsx(isCollapsed ? 'space-y-1' : 'space-y-2')}>
            {visibleItems.map(item => renderItem(item))}
          </ul>
        </nav>

        {/* Collapse button */}
        {showCollapseButton && (
          <div className={clsx('border-t border-[var(--border-primary)]', isCollapsed ? 'p-2' : 'p-4')}>
            <Button
              variant="ghost"
              size="sm"
              onClick={onToggleCollapse}
              className={clsx(
                'w-full flex items-center justify-center',
                isCollapsed ? 'p-2' : 'px-4 py-2'
              )}
              aria-label={isCollapsed ? 'Expandir sidebar' : 'Contraer sidebar'}
            >
              {isCollapsed ? (
                <ChevronRight className="w-4 h-4" />
              ) : (
                <>
                  <ChevronLeft className="w-4 h-4 mr-2" />
                  <span className="text-sm">Contraer</span>
                </>
              )}
            </Button>
          </div>
        )}

        {/* Footer */}
        {showFooter && !isCollapsed && (
          <div className="p-4 border-t border-[var(--border-primary)]">
            <div className="text-xs text-[var(--text-tertiary)] text-center">
              Panadería IA v2.0.0
            </div>
          </div>
        )}
      </aside>

      {/* Mobile Drawer */}
      <aside
        className={clsx(
          'fixed inset-y-0 left-0 w-[var(--sidebar-width)] max-w-[85vw]',
          'bg-[var(--bg-primary)] border-r border-[var(--border-primary)]',
          'transition-transform duration-300 ease-in-out z-[var(--z-modal)]',
          'lg:hidden flex flex-col',
          'shadow-xl',
          isOpen ? 'translate-x-0' : '-translate-x-full'
        )}
        aria-label="Navegación principal"
        role="dialog"
        aria-modal="true"
      >
        {/* Mobile header */}
        <div className="flex items-center justify-between p-4 border-b border-[var(--border-primary)]">
          <h2 className="text-lg font-semibold text-[var(--text-primary)]">
            Navegación
          </h2>
          <Button
            variant="ghost"
            size="sm"
            onClick={onClose}
            className="p-2"
            aria-label="Cerrar navegación"
          >
            <Menu className="w-4 h-4" />
          </Button>
        </div>

        {/* Navigation */}
        <nav className="flex-1 p-4 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent">
          <ul className="space-y-2 pb-4">
            {visibleItems.map(item => renderItem(item))}
          </ul>
        </nav>

        {/* Footer */}
        {showFooter && (
          <div className="p-4 border-t border-[var(--border-primary)]">
            <div className="text-xs text-[var(--text-tertiary)] text-center">
              Panadería IA v2.0.0
            </div>
          </div>
        )}
      </aside>
    </>
  );
});

Sidebar.displayName = 'Sidebar';