
// ============================================
// THEME SYSTEM
// ============================================
const THEMES = {
  dark: {
    id: 'dark',
    label: 'Oscuro',
    icon: 'fas fa-moon',
    preview: 'linear-gradient(135deg, #1b1c20, #000)',
    vars: {
      '--bg-body': '#000000',
      '--bg-primary': '#1b1c20',
      '--bg-secondary': '#252628',
      '--bg-tertiary': '#2a2b2f',
      '--bg-hover': '#2f3035',
      '--bg-glass': 'rgba(27,28,32,0.85)',
      '--border-primary': 'rgba(255,255,255,0.06)',
      '--border-hover': 'rgba(255,255,255,0.12)',
      '--text-primary': '#ffffff',
      '--text-secondary': '#d1d5db',
      '--text-tertiary': '#9ca3af',
      '--text-muted': '#6b7280',
      '--accent': '#fae0d1',
      '--accent-hover': '#f5d0ba',
      '--accent-bg': 'rgba(250,224,209,0.1)',
      '--accent-bg-hover': 'rgba(250,224,209,0.15)',
      '--shadow': '0 8px 32px rgba(0,0,0,0.4)',
      '--shadow-lg': '0 20px 60px rgba(0,0,0,0.5)',
    }
  },
  light: {
    id: 'light',
    label: 'Claro',
    icon: 'fas fa-sun',
    preview: 'linear-gradient(135deg, #f8f9fb, #e8e9ed)',
    vars: {
      '--bg-body': '#f0f1f5',
      '--bg-primary': '#ffffff',
      '--bg-secondary': '#f8f9fb',
      '--bg-tertiary': '#f0f1f5',
      '--bg-hover': '#ecedf1',
      '--bg-glass': 'rgba(255,255,255,0.9)',
      '--border-primary': 'rgba(0,0,0,0.08)',
      '--border-hover': 'rgba(0,0,0,0.15)',
      '--text-primary': '#1a1a2e',
      '--text-secondary': '#374151',
      '--text-tertiary': '#6b7280',
      '--text-muted': '#9ca3af',
      '--accent': '#c4956a',
      '--accent-hover': '#b4855a',
      '--accent-bg': 'rgba(196,149,106,0.1)',
      '--accent-bg-hover': 'rgba(196,149,106,0.18)',
      '--shadow': '0 4px 16px rgba(0,0,0,0.06)',
      '--shadow-lg': '0 12px 40px rgba(0,0,0,0.1)',
    }
  },
  space: {
    id: 'space',
    label: 'Espacial',
    icon: 'fas fa-rocket',
    preview: 'linear-gradient(135deg, #050510, #0a0a2e)',
    vars: {
      '--bg-body': '#050510',
      '--bg-primary': 'rgba(10,10,30,0.8)',
      '--bg-secondary': 'rgba(15,15,40,0.7)',
      '--bg-tertiary': 'rgba(20,20,50,0.6)',
      '--bg-hover': 'rgba(30,30,70,0.5)',
      '--bg-glass': 'rgba(10,10,30,0.75)',
      '--border-primary': 'rgba(100,130,255,0.1)',
      '--border-hover': 'rgba(100,130,255,0.2)',
      '--text-primary': '#e0e4ff',
      '--text-secondary': '#b0b8e0',
      '--text-tertiary': '#7880a8',
      '--text-muted': '#4a507a',
      '--accent': '#7c9dff',
      '--accent-hover': '#6b8cf0',
      '--accent-bg': 'rgba(124,157,255,0.1)',
      '--accent-bg-hover': 'rgba(124,157,255,0.18)',
      '--shadow': '0 8px 32px rgba(0,0,40,0.5)',
      '--shadow-lg': '0 20px 60px rgba(0,0,40,0.6)',
    }
  },
  vivid: {
    id: 'vivid',
    label: 'Vívido',
    icon: 'fas fa-palette',
    preview: 'linear-gradient(135deg, #fef3f0, #f0f0fe)',
    vars: {
      '--bg-body': '#faf5f3',
      '--bg-primary': '#fff9f7',
      '--bg-secondary': '#fef3f0',
      '--bg-tertiary': '#fcefec',
      '--bg-hover': '#fde8e3',
      '--bg-glass': 'rgba(255,249,247,0.92)',
      '--border-primary': 'rgba(200,160,140,0.15)',
      '--border-hover': 'rgba(200,160,140,0.25)',
      '--text-primary': '#2d2a3e',
      '--text-secondary': '#504b5e',
      '--text-tertiary': '#8a829a',
      '--text-muted': '#b0a8c0',
      '--accent': '#e8805a',
      '--accent-hover': '#d8704a',
      '--accent-bg': 'rgba(232,128,90,0.1)',
      '--accent-bg-hover': 'rgba(232,128,90,0.18)',
      '--shadow': '0 4px 20px rgba(180,120,100,0.08)',
      '--shadow-lg': '0 12px 40px rgba(180,120,100,0.12)',
    }
  },
};

const THEME_STORAGE_KEY = 'esperiency_theme';

function loadTheme() {
  try {
    const saved = localStorage.getItem(THEME_STORAGE_KEY);
    if (saved && THEMES[saved]) return saved;
  } catch (e) {}
  return 'dark';
}

function applyThemeToDOM(themeId) {
  const theme = THEMES[themeId];
  if (!theme) return;
  const root = document.documentElement;
  Object.entries(theme.vars).forEach(([key, val]) => root.style.setProperty(key, val));
  // Set body background
  document.body.style.backgroundColor = theme.vars['--bg-body'];
  // Set a data attribute for conditional styling
  root.setAttribute('data-theme', themeId);
}

// Space background component
function SpaceBackground() {
  return React.createElement('div', {
    className: 'space-bg-container',
    style: { position: 'fixed', inset: 0, zIndex: 0, pointerEvents: 'none', overflow: 'hidden' }
  },
    React.createElement('div', { className: 'space-stars space-stars-sm' }),
    React.createElement('div', { className: 'space-stars space-stars-md' }),
    React.createElement('div', { className: 'space-stars space-stars-lg' }),
    React.createElement('div', { className: 'space-nebula space-nebula-1' }),
    React.createElement('div', { className: 'space-nebula space-nebula-2' }),
    React.createElement('div', { className: 'space-shooting-star', style: { top: '15%', left: '25%', animationDelay: '0s' } }),
    React.createElement('div', { className: 'space-shooting-star', style: { top: '40%', left: '65%', animationDelay: '2s' } }),
    React.createElement('div', { className: 'space-shooting-star', style: { top: '65%', left: '40%', animationDelay: '4.5s' } }),
    React.createElement('div', { className: 'space-shooting-star', style: { top: '25%', left: '80%', animationDelay: '6s' } }),
  );
}

// Theme context
const ThemeContext = React.createContext({ theme: 'dark', setTheme: () => {} });

function ThemeProvider({ children }) {
  const [theme, setThemeState] = React.useState(() => loadTheme());

  const setTheme = React.useCallback((id) => {
    if (!THEMES[id]) return;
    setThemeState(id);
    localStorage.setItem(THEME_STORAGE_KEY, id);
    applyThemeToDOM(id);
  }, []);

  // Apply on mount
  React.useEffect(() => { applyThemeToDOM(theme); }, []);

  return React.createElement(ThemeContext.Provider, { value: { theme, setTheme } },
    theme === 'space' && React.createElement(SpaceBackground),
    children
  );
}

function useTheme() { return React.useContext(ThemeContext); }

// Theme selector widget for customize mode
function ThemeSelector() {
  const { theme, setTheme } = useTheme();
  return React.createElement('div', { className: 'flex items-center gap-1.5' },
    Object.entries(THEMES).map(([id, t]) =>
      React.createElement('button', {
        key: id,
        onClick: () => setTheme(id),
        title: t.label,
        className: `relative w-8 h-8 rounded-lg flex items-center justify-center transition-all duration-200 ${
          theme === id
            ? 'ring-2 ring-offset-1 scale-105'
            : 'opacity-60 hover:opacity-100 hover:scale-105'
        }`,
        style: {
          background: t.preview,
          ringColor: theme === id ? 'var(--accent)' : undefined,
          ringOffsetColor: theme === id ? 'var(--bg-primary)' : undefined,
        }
      },
        React.createElement('i', {
          className: `${t.icon} text-[10px] ${
            id === 'light' || id === 'vivid' ? 'text-gray-700' : 'text-white/80'
          }`
        }),
        theme === id && React.createElement('div', {
          className: 'absolute -bottom-1 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full',
          style: { background: 'var(--accent)' }
        })
      )
    )
  );
}

// Mini skeleton dashboard preview for theme cards
function ThemeSkeletonPreview({ themeId, layout }) {
  const t = THEMES[themeId];
  if (!t) return null;
  const v = t.vars;
  // We render a tiny 6-col grid mimicking the current layout
  return (
    <div className="w-full rounded-md overflow-hidden" style={{ background: v['--bg-body'], padding: '3px' }}>
      <div className="flex gap-[2px]" style={{ height: '52px' }}>
        {/* Mini sidebar */}
        <div className="flex-shrink-0 rounded-sm flex flex-col gap-[2px] py-[2px] px-[1px]" style={{ width: '10px', background: v['--bg-body'] }}>
          <div className="w-[6px] h-[6px] rounded-full mx-auto" style={{ background: v['--accent'], opacity: 0.6 }}></div>
          <div className="w-[4px] h-[2px] rounded-full mx-auto mt-auto" style={{ background: v['--text-muted'], opacity: 0.3 }}></div>
          <div className="w-[4px] h-[2px] rounded-full mx-auto" style={{ background: v['--text-muted'], opacity: 0.3 }}></div>
          <div className="w-[4px] h-[2px] rounded-full mx-auto" style={{ background: v['--text-muted'], opacity: 0.3 }}></div>
        </div>
        {/* Main content area with mini grid */}
        <div className="flex-1 overflow-hidden">
          <div className="grid gap-[2px]" style={{ gridTemplateColumns: 'repeat(6, 1fr)' }}>
            {(layout || []).slice(0, 10).map((item, idx) => {
              const sp = Math.min(item.span || 2, 6);
              const h = sp === 6 ? '6px' : sp >= 4 ? '10px' : '10px';
              return (
                <div 
                  key={idx} 
                  className="rounded-sm"
                  style={{ 
                    gridColumn: `span ${sp}`, 
                    height: h, 
                    background: v['--bg-primary'],
                    border: `0.5px solid ${v['--border-primary']}`,
                  }}
                >
                  {sp >= 3 && (
                    <div className="flex items-center gap-[1px] h-full px-[2px]">
                      <div className="rounded-full" style={{ width: '3px', height: '3px', background: v['--accent'], opacity: 0.5 }}></div>
                      <div className="rounded-sm flex-1" style={{ height: '2px', background: v['--text-muted'], opacity: 0.2 }}></div>
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

// Theme card for dock
function ThemeDockCard({ themeId, layout }) {
  const { theme, setTheme } = useTheme();
  const t = THEMES[themeId];
  if (!t) return null;
  const isActive = theme === themeId;
  const isDark = themeId === 'dark' || themeId === 'space';
  return (
    <button
      onClick={() => setTheme(themeId)}
      className={`cust-dock-item flex flex-col rounded-xl border transition-all duration-200 overflow-hidden group/theme hover:scale-[1.03] ${
        isActive
          ? 'ring-2 ring-offset-1 scale-[1.02]'
          : 'opacity-75 hover:opacity-100'
      }`}
      style={{
        background: t.vars['--bg-primary'],
        borderColor: isActive ? t.vars['--accent'] : t.vars['--border-primary'],
        '--tw-ring-color': t.vars['--accent'],
        '--tw-ring-offset-color': 'var(--bg-glass)',
      }}
    >
      <ThemeSkeletonPreview themeId={themeId} layout={layout} />
      <div className="flex items-center gap-2 px-2.5 py-2">
        <i className={`${t.icon} text-xs`} style={{ color: t.vars['--accent'] }}></i>
        <span className="text-xs font-medium" style={{ color: t.vars['--text-primary'] }}>{t.label}</span>
        {isActive && (
          <i className="fas fa-check-circle text-[10px] ml-auto" style={{ color: t.vars['--accent'] }}></i>
        )}
      </div>
    </button>
  );
}

// Componentes disponibles globalmente (cargados desde archivos externos)
const TenantsPage = window.TenantsPage;
const AddTenantPage = window.AddTenantPage;
const AnalyticsDashboard = window.AnalyticsDashboard;
const AddApartmentPage = window.AddApartmentPage;
const AdminPage = window.AdminPage;

// ============================================
// COMPONENTE APARTMENTS PAGE
// ============================================
const ApartmentsPage = ({ setCurrentPage }) => {
  const [apartments, setApartments] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [searchTerm, setSearchTerm] = React.useState('');
  const [tenants, setTenants] = React.useState([]);
  const [viewMode, setViewMode] = React.useState('grid'); // 'grid' o 'table'
  const [selectedApartment, setSelectedApartment] = React.useState(null);
  const [currentPhotoIndex, setCurrentPhotoIndex] = React.useState(0);
  const [editingApartment, setEditingApartment] = React.useState(null);
  const [userRole, setUserRole] = React.useState('user');
  const [refreshKey, setRefreshKey] = React.useState(0);
  const [orgName, setOrgName] = React.useState(() => localStorage.getItem('organizationName') || '');

  const getJWTFromStorage = () => {
    return sessionStorage.getItem('authToken') || 
           sessionStorage.getItem('jwt') || 
           localStorage.getItem('authToken') || 
           localStorage.getItem('jwt');
  };

  // Función para recargar datos
  const reloadData = () => {
    setRefreshKey(prev => prev + 1);
    setLoading(true);
  };

  // Obtener rol del usuario y nombre de organización
  React.useEffect(() => {
    const token = getJWTFromStorage();
    if (token) {
      try {
        const payload = parseJWT(token);
        // Buscar rol en diferentes propiedades posibles
        const role = payload.role || payload.userRole || payload.tipo || payload.type || 'admin';
        setUserRole(role);
        console.log('User role detected:', role, payload);
        
        // Obtener nombre de organización
        const organizationName = localStorage.getItem('organizationName') || payload.organizationName || 'Mi Organización';
        setOrgName(organizationName);
      } catch (e) {
        console.error('Error parsing JWT:', e);
        setUserRole('admin'); // Default a admin para desarrollo
      }
    } else {
      setUserRole('admin'); // Default a admin si no hay token
    }
  }, []);

  // Cargar departamentos y tenants
  React.useEffect(() => {
    const loadData = async () => {
      try {
        let organizationId = window.currentOrganizationId;
        
        if (!organizationId) {
          const token = getJWTFromStorage();
          if (token) {
            const payload = parseJWT(token);
            organizationId = payload.organizationId;
          }
        }
        
        if (organizationId) {
          // Cargar departamentos
          const aptResponse = await fetch(`http://localhost:3000/api/apartments`, {
            headers: {
              'Authorization': `Bearer ${getJWTFromStorage()}`
            }
          });
          
          if (aptResponse.ok) {
            const aptResult = await aptResponse.json();
            setApartments(aptResult.data || []);
          }

          // Cargar tenants para mostrar nombres
          const tenantResponse = await fetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
            headers: {
              'Authorization': `Bearer ${getJWTFromStorage()}`
            }
          });
          
          if (tenantResponse.ok) {
            const tenantResult = await tenantResponse.json();
            setTenants(tenantResult.data || []);
          }
        }
      } catch (error) {
        console.error('Error cargando departamentos:', error);
      } finally {
        setLoading(false);
      }
    };
    
    loadData();
  }, [refreshKey]);

  // Filtrar departamentos
  const filteredApartments = apartments.filter(apt =>
    apt.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
    apt.address?.toLowerCase().includes(searchTerm.toLowerCase())
  );

  // Obtener nombres de residentes (titulares)
  const getResidentNames = (residentIds) => {
    if (!residentIds || residentIds.length === 0) return 'Sin residentes';
    const names = residentIds.map(id => {
      const tenant = tenants.find(t => t.id === id);
      return tenant ? tenant.name : 'Desconocido';
    });
    return names.join(', ');
  };

  // Obtener tenant completo
  const getTenantById = (id) => {
    return tenants.find(t => t.id === id);
  };

  // Vista expandida del departamento
  const ApartmentDetailView = ({ apartment, onClose }) => {
    const [photoIndex, setPhotoIndex] = React.useState(0);
    const [showMenu, setShowMenu] = React.useState(false);
    const [showLightbox, setShowLightbox] = React.useState(false);
    const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
    const [showReceiptModal, setShowReceiptModal] = React.useState(false);
    const [showPaymentHistoryModal, setShowPaymentHistoryModal] = React.useState(false);
    const [showExpedienteModal, setShowExpedienteModal] = React.useState(false);
    const [lastReceipt, setLastReceipt] = React.useState(null);
    const photos = apartment.photos || [];
    const hasMultiplePhotos = photos.length > 1;
    // Mostrar opciones de admin si el rol es admin, owner, administrador
    const isAdmin = ['admin', 'owner', 'administrador', 'Admin', 'Owner'].includes(userRole);

    const handleEdit = () => {
      setEditingApartment(apartment);
      setSelectedApartment(null);
    };

    const handleBlock = async () => {
      try {
        await fetch(`http://localhost:3000/api/apartments/${apartment.id}`, {
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${getJWTFromStorage()}`
          },
          body: JSON.stringify({ ...apartment, blocked: !apartment.blocked })
        });
        window.showSuccess?.(apartment.blocked ? 'Departamento desbloqueado' : 'Departamento bloqueado');
        reloadData();
        onClose();
      } catch (error) {
        window.showError?.('Error al actualizar');
      }
    };

    const handleDelete = async () => {
      try {
        await fetch(`http://localhost:3000/api/apartments/${apartment.id}`, {
          method: 'DELETE',
          headers: { 'Authorization': `Bearer ${getJWTFromStorage()}` }
        });
        window.showSuccess?.('Departamento eliminado');
        reloadData();
        onClose();
      } catch (error) {
        window.showError?.('Error al eliminar');
      }
    };

    const confirmDelete = () => {
      setShowDeleteConfirm(true);
    };

    return (
      <div className="fixed inset-0 z-50 overflow-y-auto" style={{ background: 'rgba(0,0,0,0.7)', backdropFilter: 'blur(16px)' }}>
        <div className="min-h-screen py-8 px-4">
          <div className="max-w-7xl mx-auto rounded-3xl p-6 border" style={{ background: 'var(--bg-glass)', backdropFilter: 'blur(20px)', borderColor: 'var(--border-primary)' }}>
            {/* Header */}
            <div className="flex items-center justify-between mb-6">
              <button
                onClick={onClose}
                className="flex items-center text-gray-400 hover:text-white transition-colors"
              >
                <svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
                </svg>
                Volver a Departamentos
              </button>
              <div className="flex items-center gap-2">
                <button
                  onClick={handleEdit}
                  className="px-4 py-2 bg-transparent hover:bg-blue-600 text-white border border-gray-700 hover:border-blue-600 rounded-lg transition-colors flex items-center gap-2"
                >
                  <i className="fas fa-edit"></i>
                  Modificar
                </button>
                {isAdmin && (
                  <div className="relative">
                    <button
                      onClick={() => setShowMenu(!showMenu)}
                      className="px-3 py-2 text-gray-400 hover:text-white transition-colors"
                    >
                      <i className="fas fa-ellipsis-v"></i>
                    </button>
                    {showMenu && (
                      <div className="absolute right-0 mt-2 w-48 bg-[#1a1a1a] border border-gray-800 rounded-lg shadow-xl z-10">
                        <button
                          onClick={handleBlock}
                          className="w-full px-4 py-3 text-left text-gray-300 hover:bg-gray-800 flex items-center gap-3 transition-colors"
                        >
                          <i className={`fas ${apartment.blocked ? 'fa-unlock' : 'fa-ban'} text-yellow-500`}></i>
                          {apartment.blocked ? 'Desbloquear' : 'Bloquear'}
                        </button>
                        <button
                          onClick={confirmDelete}
                          className="w-full px-4 py-3 text-left text-red-400 hover:bg-gray-800 flex items-center gap-3 transition-colors"
                        >
                          <i className="fas fa-trash"></i>
                          Eliminar
                        </button>
                      </div>
                    )}
                  </div>
                )}
              </div>
            </div>

            {/* Content Grid */}
            <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
              {/* Panel Izquierdo - Fotos e Info */}
              <div className="lg:col-span-2 space-y-4">
                {/* Foto Principal - Click para expandir */}
                <div 
                  className="aspect-video rounded-2xl overflow-hidden bg-gray-900 cursor-pointer relative group"
                  onClick={() => photos.length > 0 && setShowLightbox(true)}
                >
                  {photos.length > 0 ? (
                    <>
                      <img 
                        src={photos[photoIndex]} 
                        alt={apartment.name}
                        className="w-full h-full object-cover"
                      />
                      <div className="absolute inset-0 bg-black/30 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
                        <i className="fas fa-expand text-white text-2xl"></i>
                      </div>
                    </>
                  ) : (
                    <div className="w-full h-full flex items-center justify-center">
                      <i className="fas fa-building text-6xl text-gray-700"></i>
                    </div>
                  )}
                </div>

                {/* Lightbox para ver imagen grande */}
                {showLightbox && photos.length > 0 && (
                  <div 
                    className="fixed inset-0 bg-black/95 z-[60] flex items-center justify-center"
                    onClick={() => setShowLightbox(false)}
                  >
                    <button
                      onClick={(e) => { e.stopPropagation(); setShowLightbox(false); }}
                      className="absolute top-4 right-4 text-white hover:text-gray-300 text-2xl z-10"
                    >
                      <i className="fas fa-times"></i>
                    </button>
                    
                    {/* Navegación */}
                    {hasMultiplePhotos && (
                      <>
                        <button
                          onClick={(e) => { e.stopPropagation(); setPhotoIndex(prev => prev === 0 ? photos.length - 1 : prev - 1); }}
                          className="absolute left-4 text-white hover:text-gray-300 text-3xl z-10"
                        >
                          <i className="fas fa-chevron-left"></i>
                        </button>
                        <button
                          onClick={(e) => { e.stopPropagation(); setPhotoIndex(prev => prev === photos.length - 1 ? 0 : prev + 1); }}
                          className="absolute right-4 text-white hover:text-gray-300 text-3xl z-10"
                        >
                          <i className="fas fa-chevron-right"></i>
                        </button>
                      </>
                    )}
                    
                    {/* Imagen grande */}
                    <img 
                      src={photos[photoIndex]} 
                      alt={apartment.name}
                      className="max-w-[90vw] max-h-[90vh] object-contain"
                      onClick={(e) => e.stopPropagation()}
                    />
                    
                    {/* Contador */}
                    <div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 text-white bg-black/50 px-4 py-2 rounded-full">
                      {photoIndex + 1} / {photos.length}
                    </div>
                  </div>
                )}

                {/* Carrusel de fotos */}
                {hasMultiplePhotos && (
                  <div className="flex gap-2 overflow-x-auto pb-2">
                    {photos.map((photo, idx) => (
                      <button
                        key={idx}
                        onClick={() => setPhotoIndex(idx)}
                        className={`flex-shrink-0 w-20 h-20 rounded-lg overflow-hidden border-2 transition-colors ${
                          idx === photoIndex ? 'border-blue-500' : 'border-transparent hover:border-gray-600'
                        }`}
                      >
                        <img src={photo} alt={`Foto ${idx + 1}`} className="w-full h-full object-cover" />
                      </button>
                    ))}
                  </div>
                )}

                {/* Nombre, Dirección y Estado */}
                <div className="bg-white/5 backdrop-blur-lg rounded-2xl p-5 border border-white/10">
                  <div className="flex items-start justify-between">
                    <div>
                      <h1 className="text-3xl font-bold text-white mb-2">{apartment.name}</h1>
                      {apartment.address && (
                        <div className="flex items-center gap-2 text-gray-400">
                          <i className="fas fa-map-marker-alt text-blue-500"></i>
                          <span className="text-sm">{apartment.address}</span>
                        </div>
                      )}
                    </div>
                    <span className={`text-sm px-3 py-1 rounded-full ${
                      apartment.status === 'occupied' 
                        ? 'bg-green-500/20 text-green-400 border border-green-500/30' 
                        : 'bg-gray-500/20 text-gray-400 border border-gray-500/30'
                    }`}>
                      {apartment.status === 'occupied' ? 'Ocupado' : 'Disponible'}
                    </span>
                  </div>
                </div>

                {/* Arrendatarios */}
                <div className="bg-white/5 backdrop-blur-lg rounded-xl p-5 border border-white/10">
                  <h3 className="text-lg font-semibold text-white mb-4 flex items-center gap-2">
                    <i className="fas fa-users text-blue-500"></i>
                    Arrendatarios
                  </h3>
                  
                  {apartment.residents && apartment.residents.length > 0 ? (
                    <div className="space-y-3">
                      {apartment.residents.map(residentId => {
                        const tenant = getTenantById(residentId);
                        return tenant ? (
                          <div key={residentId} className="flex items-center justify-between p-3 bg-black/30 rounded-lg border border-white/5">
                            <div className="flex items-center gap-3">
                              <div className="w-10 h-10 rounded-full bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center text-white font-semibold shadow-lg">
                                {tenant.name?.charAt(0)?.toUpperCase() || 'T'}
                              </div>
                              <div>
                                <p className="text-white font-medium">{tenant.name}</p>
                                <p className="text-xs text-blue-400">Titular</p>
                              </div>
                            </div>
                            <button className="text-gray-400 hover:text-white">
                              <i className="fas fa-chevron-right"></i>
                            </button>
                          </div>
                        ) : null;
                      })}
                    </div>
                  ) : (
                    <p className="text-gray-500">Sin arrendatarios asignados</p>
                  )}

                  {/* Subresidentes */}
                  {apartment.subResidents && apartment.subResidents.length > 0 && (
                    <div className="mt-4 pt-4 border-t border-white/10">
                      <p className="text-sm text-gray-400 mb-3">Subresidentes</p>
                      <div className="space-y-2">
                        {apartment.subResidents.map((name, idx) => (
                          <div key={idx} className="flex items-center gap-3 p-2 bg-black/30 rounded-lg border border-white/5">
                            <div className="w-8 h-8 rounded-full bg-gray-700 flex items-center justify-center text-gray-300 text-sm">
                              {name?.charAt(0)?.toUpperCase() || 'S'}
                            </div>
                            <span className="text-gray-300 text-sm">{name}</span>
                          </div>
                        ))}
                      </div>
                    </div>
                  )}
                </div>
              </div>

              {/* Panel Derecho - Acciones y Info */}
              <div className="space-y-4">
                {/* Calidad de Arrendatario */}
                {(() => {
                  const residentTenants = (apartment.residents || []).map(id => getTenantById(id)).filter(Boolean);
                  let grade = 'N/A', label = 'Sin arrendatarios', subtitle = 'Sin datos', colorClass = 'gray';
                  if (residentTenants.length > 0) {
                    const total = residentTenants.length;
                    const currentCount = residentTenants.filter(t => t.paymentStatus === 'current' || t.paymentStatus === 'al corriente').length;
                    const ratio = currentCount / total;
                    if (ratio === 1) { grade = 'A+'; label = 'Excelente'; subtitle = 'Pagos puntuales'; colorClass = 'green'; }
                    else if (ratio >= 0.75) { grade = 'A'; label = 'Bueno'; subtitle = 'Mayoría al corriente'; colorClass = 'green'; }
                    else if (ratio >= 0.5) { grade = 'B'; label = 'Regular'; subtitle = 'Algunos pagos pendientes'; colorClass = 'yellow'; }
                    else if (ratio >= 0.25) { grade = 'C'; label = 'Deficiente'; subtitle = 'Pagos atrasados frecuentes'; colorClass = 'orange'; }
                    else { grade = 'D'; label = 'Crítico'; subtitle = 'Pagos muy atrasados'; colorClass = 'red'; }
                  }
                  const colors = {
                    green: { bg: 'bg-green-500/20', border: 'border-green-500/30', text: 'text-green-400' },
                    yellow: { bg: 'bg-yellow-500/20', border: 'border-yellow-500/30', text: 'text-yellow-400' },
                    orange: { bg: 'bg-orange-500/20', border: 'border-orange-500/30', text: 'text-orange-400' },
                    red: { bg: 'bg-red-500/20', border: 'border-red-500/30', text: 'text-red-400' },
                    gray: { bg: 'bg-gray-500/20', border: 'border-gray-500/30', text: 'text-gray-400' },
                  };
                  const c = colors[colorClass];
                  return (
                    <div className="bg-white/5 backdrop-blur-lg rounded-xl p-5 border border-white/10">
                      <h3 className="text-sm font-medium text-gray-400 mb-3">Calidad de Arrendatario</h3>
                      <div className="flex items-center gap-3">
                        <div className={`w-16 h-16 rounded-full ${c.bg} flex items-center justify-center border ${c.border}`}>
                          <span className={`text-2xl font-bold ${c.text}`}>{grade}</span>
                        </div>
                        <div>
                          <p className="text-white font-semibold">{label}</p>
                          <p className="text-xs text-gray-400">{subtitle}</p>
                        </div>
                      </div>
                    </div>
                  );
                })()}

                {/* Finalización de Contrato */}
                {(() => {
                  const residentTenants = (apartment.residents || []).map(id => getTenantById(id)).filter(Boolean);
                  const contractDates = residentTenants
                    .map(t => t.endDate || t.contractEnd)
                    .filter(d => d && d !== 'Sin definir')
                    .map(d => new Date(d))
                    .filter(d => !isNaN(d.getTime()));
                  const nearestDate = contractDates.length > 0 ? contractDates.sort((a, b) => a - b)[0] : null;
                  const now = new Date();
                  let iconColor = 'yellow', bgColor = 'bg-yellow-500/20', borderColor = 'border-yellow-500/30';
                  if (nearestDate) {
                    const daysLeft = Math.ceil((nearestDate - now) / (1000 * 60 * 60 * 24));
                    if (daysLeft < 0) { iconColor = 'red'; bgColor = 'bg-red-500/20'; borderColor = 'border-red-500/30'; }
                    else if (daysLeft <= 30) { iconColor = 'yellow'; bgColor = 'bg-yellow-500/20'; borderColor = 'border-yellow-500/30'; }
                    else { iconColor = 'green'; bgColor = 'bg-green-500/20'; borderColor = 'border-green-500/30'; }
                  }
                  return (
                    <div className="bg-white/5 backdrop-blur-lg rounded-xl p-5 border border-white/10">
                      <h3 className="text-sm font-medium text-gray-400 mb-3">Finalización de Contrato</h3>
                      <div className="flex items-center gap-3">
                        <div className={`w-12 h-12 rounded-full ${bgColor} flex items-center justify-center border ${borderColor}`}>
                          <i className={`fas fa-calendar-alt text-xl text-${iconColor}-500`}></i>
                        </div>
                        <div>
                          <p className="text-white font-semibold">
                            {nearestDate
                              ? nearestDate.toLocaleDateString('es-MX', { day: 'numeric', month: 'long', year: 'numeric' })
                              : 'Sin definir'}
                          </p>
                          <p className="text-xs text-gray-400">
                            {nearestDate
                              ? (() => {
                                  const daysLeft = Math.ceil((nearestDate - now) / (1000 * 60 * 60 * 24));
                                  if (daysLeft < 0) return `Venció hace ${Math.abs(daysLeft)} días`;
                                  if (daysLeft === 0) return 'Vence hoy';
                                  return `Faltan ${daysLeft} días`;
                                })()
                              : 'Fecha de término'}
                          </p>
                        </div>
                      </div>
                    </div>
                  );
                })()}

                {/* Reportes */}
                <div className="bg-white/5 backdrop-blur-lg rounded-xl p-5 border border-white/10">
                  <h3 className="text-sm font-medium text-gray-400 mb-3">Reportes</h3>
                  <div className="flex items-center justify-between">
                    <div className="flex items-center gap-3">
                      <div className="w-10 h-10 rounded-full bg-orange-500/20 flex items-center justify-center border border-orange-500/30">
                        <i className="fas fa-exclamation-triangle text-orange-500"></i>
                      </div>
                      <div>
                        <p className="text-white font-semibold">{apartment.reports?.length || 0}</p>
                        <p className="text-xs text-gray-400">Reportes activos</p>
                      </div>
                    </div>
                    <button className="text-blue-500 hover:text-blue-400 text-sm">Ver todos</button>
                  </div>
                </div>

                {/* Accesos Directos */}
                <div className="bg-white/5 backdrop-blur-lg rounded-xl p-5 space-y-3 border border-white/10">
                  <h3 className="text-sm font-medium text-gray-400 mb-1">Accesos Directos</h3>
                  
                  {(() => {
                    const rid = apartment.residents?.[0];
                    const t = rid ? getTenantById(rid) : null;
                    const hasPaid = t?.paymentStatus === 'current' || t?.paymentStatus === 'advanced';
                    const hasPayments = t?.paymentHistory?.length > 0;
                    return (
                      <button 
                        onClick={() => setShowReceiptModal(true)}
                        className={`w-full flex items-center gap-3 p-3 bg-gradient-to-r ${hasPaid ? 'from-green-500/20 to-emerald-500/20 hover:from-green-500/30 hover:to-emerald-500/30 border-green-500/20' : 'from-orange-500/20 to-red-500/20 hover:from-orange-500/30 hover:to-red-500/30 border-orange-500/20'} rounded-lg transition-all text-left border`}
                      >
                        <i className={`fas fa-receipt ${hasPaid ? 'text-green-400' : 'text-orange-400'} w-5`}></i>
                        <div className="flex-1">
                          <span className="text-white block">Último Recibo</span>
                          <span className={`text-xs ${hasPaid ? 'text-green-400/70' : 'text-orange-400/70'}`}>
                            {!hasPayments ? 'Sin pagos registrados' : hasPaid ? 'Pago al corriente' : 'Pago pendiente'}
                          </span>
                        </div>
                        <i className={`fas fa-chevron-right ${hasPaid ? 'text-green-500/50' : 'text-orange-500/50'}`}></i>
                      </button>
                    );
                  })()}
                  
                  <button 
                    onClick={() => setShowPaymentHistoryModal(true)}
                    className="w-full flex items-center gap-3 p-3 bg-[#1a1a1a] hover:bg-[#222] rounded-lg transition-colors text-left"
                  >
                    <i className="fas fa-money-bill-wave text-green-500 w-5"></i>
                    <span className="text-white">Historial de Pagos</span>
                    <i className="fas fa-chevron-right ml-auto text-gray-600"></i>
                  </button>
                  
                  <button 
                    onClick={() => setShowExpedienteModal(true)}
                    className="w-full flex items-center gap-3 p-3 bg-[#1a1a1a] hover:bg-[#222] rounded-lg transition-colors text-left"
                  >
                    <i className="fas fa-folder-open text-blue-500 w-5"></i>
                    <span className="text-white">Expediente del Arrendatario</span>
                    <i className="fas fa-chevron-right ml-auto text-gray-600"></i>
                  </button>
                  
                  {apartment.contractBase64 ? (
                    <a 
                      href={apartment.contractBase64}
                      download={apartment.contractFileName || 'contrato.pdf'}
                      className="w-full flex items-center gap-3 p-3 bg-[#1a1a1a] hover:bg-[#222] rounded-lg transition-colors text-left"
                    >
                      <i className="fas fa-file-contract text-purple-500 w-5"></i>
                      <span className="text-white">Descargar Contrato</span>
                      <i className="fas fa-download ml-auto text-gray-600"></i>
                    </a>
                  ) : (
                    <button className="w-full flex items-center gap-3 p-3 bg-[#1a1a1a] hover:bg-[#222] rounded-lg transition-colors text-left opacity-50 cursor-not-allowed">
                      <i className="fas fa-file-contract text-purple-500 w-5"></i>
                      <span className="text-white">Sin Contrato</span>
                      <i className="fas fa-times ml-auto text-gray-600"></i>
                    </button>
                  )}
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Modal de Confirmación para Eliminar Departamento */}
        {showDeleteConfirm && (
          <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[60]">
            <div className="bg-[#1b1c20] rounded-2xl p-6 w-full max-w-md mx-4 border border-[#252628]">
              <div className="flex items-center justify-between mb-6">
                <h3 className="text-xl font-semibold text-red-400 flex items-center">
                  <i className="fas fa-exclamation-triangle mr-2"></i>
                  Eliminar Departamento
                </h3>
                <button 
                  onClick={() => setShowDeleteConfirm(false)}
                  className="text-gray-400 hover:text-white"
                >
                  <i className="fas fa-times"></i>
                </button>
              </div>
              
              <div className="space-y-4">
                <div className="bg-red-900/30 border border-red-500/30 rounded-lg p-4">
                  <p className="text-red-300 text-center font-semibold mb-3">
                    ¿Estás seguro de que quieres eliminar este departamento?
                  </p>
                  <div className="text-sm text-gray-300 space-y-1 text-center">
                    <p><span className="text-white font-medium">{apartment.name}</span></p>
                    {apartment.address && <p className="text-gray-400">{apartment.address}</p>}
                  </div>
                  <p className="text-gray-400 text-sm text-center mt-3">
                    <i className="fas fa-warning mr-1"></i>
                    Esta acción no se puede deshacer.
                  </p>
                </div>
                
                <div className="flex gap-4">
                  <button
                    onClick={() => setShowDeleteConfirm(false)}
                    className="flex-1 px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-lg font-medium transition-colors"
                  >
                    Cancelar
                  </button>
                  <button
                    onClick={() => {
                      setShowDeleteConfirm(false);
                      handleDelete();
                    }}
                    className="flex-1 px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg font-medium transition-colors"
                  >
                    <i className="fas fa-trash mr-2"></i>
                    Eliminar
                  </button>
                </div>
              </div>
            </div>
          </div>
        )}

        {/* Modal de Recibo */}
        {showReceiptModal && (
          <div className="fixed inset-0 bg-black/60 backdrop-blur-md flex items-center justify-center z-[60]">
            <div className="bg-white rounded-lg w-full max-w-2xl mx-4 shadow-2xl overflow-hidden max-h-[90vh] flex flex-col">
              {/* Recibo estilo email */}
              <div className="p-6 overflow-y-auto flex-1" style={{fontFamily: "'Inter', sans-serif"}}>
                {(() => {
                  // Obtener el último pago del inquilino asociado
                  const residentId = apartment.residents?.[0];
                  const tenant = residentId ? getTenantById(residentId) : null;
                  const lastPayment = tenant?.paymentHistory?.length > 0 
                    ? [...tenant.paymentHistory].sort((a, b) => new Date(b.date) - new Date(a.date))[0]
                    : null;
                  
                  if (!lastPayment) {
                    return (
                      <div className="text-center py-12">
                        <div className="w-20 h-20 rounded-full bg-gray-100 flex items-center justify-center mx-auto mb-4">
                          <i className="fas fa-receipt text-gray-400 text-3xl"></i>
                        </div>
                        <p className="text-gray-600 font-medium">No hay recibos disponibles</p>
                        <p className="text-gray-400 text-sm mt-1">Aún no se han registrado pagos para este departamento</p>
                      </div>
                    );
                  }
                  
                  return (
                    <>
                      {/* Header con Esperiency */}
                      <div className="relative mb-6">
                        <div className="absolute top-0 left-0">
                          <p className="text-sm font-semibold text-gray-500">Esperiency</p>
                        </div>
                        <div className="text-center">
                          <h1 className="text-2xl font-bold text-black">{orgName || 'Mi Organización'}</h1>
                          <p className="text-gray-500">Recibo de Pago</p>
                        </div>
                      </div>

                      {/* Información del Recibo */}
                      <div className="mb-6">
                        <div className="flex justify-between items-center mb-4">
                          <h2 className="text-xl font-semibold text-black">
                            Recibo #{lastPayment.receiptNumber || `REC-${lastPayment.id?.toString().slice(-8) || Date.now()}`}
                          </h2>
                          <div className="text-right">
                            <p className="text-sm text-gray-500">Fecha de pago</p>
                            <p className="font-semibold text-black">
                              {new Date(lastPayment.date).toLocaleDateString('es-ES', {
                                year: 'numeric',
                                month: 'long',
                                day: 'numeric'
                              })}
                            </p>
                          </div>
                        </div>
                        <hr className="border-gray-300" />
                      </div>

                      {/* Información del Inquilino */}
                      <div className="mb-6">
                        <h3 className="text-lg font-semibold text-black mb-3">Información del Inquilino</h3>
                        <table className="w-full">
                          <tbody>
                            <tr>
                              <td className="py-2 text-sm text-gray-500 w-32">Inquilino:</td>
                              <td className="py-2 font-semibold text-black">{tenant?.name || 'Sin nombre'}</td>
                            </tr>
                            <tr>
                              <td className="py-2 text-sm text-gray-500">Apartamento:</td>
                              <td className="py-2 font-semibold text-black">{apartment.name}</td>
                            </tr>
                          </tbody>
                        </table>
                      </div>

                      {/* Detalles del Pago */}
                      <div className="mb-6">
                        <h3 className="text-lg font-semibold text-black mb-3">Detalles del Pago</h3>
                        <table className="w-full">
                          <tbody>
                            <tr>
                              <td className="py-2 text-sm text-gray-500 w-32">Concepto:</td>
                              <td className="py-2 font-semibold text-black">
                                {lastPayment.type === 'next-month-payment' ? 'Pago Adelantado - Próximo Mes' :
                                 lastPayment.description || 'Pago de Renta'}
                              </td>
                            </tr>
                            <tr>
                              <td className="py-2 text-sm text-gray-500">Monto Pagado:</td>
                              <td className="py-2 text-xl font-bold text-black">${lastPayment.amount?.toLocaleString() || '0'}</td>
                            </tr>
                          </tbody>
                        </table>
                      </div>

                      {/* Procesado Por */}
                      <div className="mb-6">
                        <p className="text-sm text-gray-500">
                          Pago procesado por: <span className="font-semibold text-black">{lastPayment.registeredBy || 'Sistema'}</span>
                        </p>
                        {lastPayment.note && (
                          <div className="mt-4 p-4 bg-gray-100 border-l-4 border-blue-500 rounded">
                            <p className="text-sm text-gray-600 italic">
                              <strong>Nota:</strong> {lastPayment.note}
                            </p>
                          </div>
                        )}
                      </div>

                      {/* Estado del Pago */}
                      {(() => {
                        const isPaid = tenant?.paymentStatus === 'current' || tenant?.paymentStatus === 'advanced';
                        return (
                          <div className={`text-center mb-6 p-5 border-2 ${isPaid ? 'border-green-500' : 'border-red-500'}`}>
                            <p className="text-sm text-gray-500 uppercase tracking-wider mb-1">Estado del Pago</p>
                            <p className={`text-2xl font-bold ${isPaid ? 'text-green-500' : 'text-red-500'}`}>
                              {isPaid ? 'PAGADO' : 'PENDIENTE'}
                            </p>
                            {!isPaid && tenant?.pendingAmount > 0 && (
                              <p className="text-sm text-red-400 mt-1">
                                Saldo pendiente: ${tenant.pendingAmount.toLocaleString()}
                              </p>
                            )}
                          </div>
                        );
                      })()}

                      {/* Footer */}
                      <div className="text-center pt-4 border-t border-gray-300">
                        <p className="text-xs text-gray-500">
                          Este recibo es un comprobante oficial de pago generado por {orgName || 'la organización'}
                        </p>
                        <p className="text-xs text-gray-400 mt-2">
                          Powered by Esperiency • {new Date().getFullYear()}
                        </p>
                      </div>
                    </>
                  );
                })()}
              </div>
              
              {/* Botones */}
              <div className="p-4 bg-gray-100 border-t flex gap-3 flex-shrink-0">
                <button
                  onClick={() => setShowReceiptModal(false)}
                  className="flex-1 px-4 py-3 bg-gray-500 hover:bg-gray-600 text-white rounded-lg font-medium transition-colors"
                >
                  Cerrar
                </button>
                <button
                  className="flex-1 px-4 py-3 bg-green-600 hover:bg-green-700 text-white rounded-lg font-medium transition-colors flex items-center justify-center gap-2"
                >
                  <i className="fas fa-download"></i>
                  Descargar PDF
                </button>
              </div>
            </div>
          </div>
        )}

        {/* Modal de Historial de Pagos */}
        {showPaymentHistoryModal && (
          <div className="fixed inset-0 bg-black/60 backdrop-blur-md flex items-center justify-center z-[60]">
            <div className="bg-[#1b1c20] rounded-2xl w-full max-w-3xl mx-4 shadow-2xl overflow-hidden max-h-[90vh] flex flex-col border border-[#252628]">
              <div className="p-6 border-b border-[#252628] flex items-center justify-between">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-xl bg-green-500/20 flex items-center justify-center">
                    <i className="fas fa-money-bill-wave text-green-400"></i>
                  </div>
                  <div>
                    <h3 className="text-lg font-semibold text-white">Historial de Pagos</h3>
                    <p className="text-xs text-gray-400">{apartment.name}</p>
                  </div>
                </div>
                <button onClick={() => setShowPaymentHistoryModal(false)} className="text-gray-400 hover:text-white">
                  <i className="fas fa-times text-xl"></i>
                </button>
              </div>
              <div className="p-6 overflow-y-auto flex-1">
                {(() => {
                  const residentTenants = (apartment.residents || []).map(id => getTenantById(id)).filter(Boolean);
                  const allPayments = [];
                  residentTenants.forEach(t => {
                    (t.paymentHistory || []).forEach(p => {
                      allPayments.push({ ...p, tenantName: t.name });
                    });
                  });
                  allPayments.sort((a, b) => new Date(b.date) - new Date(a.date));
                  
                  if (allPayments.length === 0) {
                    return (
                      <div className="text-center py-12">
                        <div className="w-16 h-16 rounded-full bg-gray-800 flex items-center justify-center mx-auto mb-4">
                          <i className="fas fa-receipt text-gray-500 text-2xl"></i>
                        </div>
                        <p className="text-gray-400">No hay pagos registrados</p>
                      </div>
                    );
                  }
                  
                  return (
                    <div className="space-y-3">
                      <div className="grid grid-cols-5 gap-2 text-xs text-gray-500 uppercase tracking-wider px-4 pb-2 border-b border-[#252628]">
                        <span>Fecha</span>
                        <span>Concepto</span>
                        <span>Método</span>
                        <span className="text-right">Monto</span>
                        <span className="text-right">Recibo</span>
                      </div>
                      {allPayments.map((p, idx) => (
                        <div key={idx} className="grid grid-cols-5 gap-2 items-center px-4 py-3 bg-[#252628] rounded-lg hover:bg-[#35383d] transition-colors">
                          <span className="text-sm text-gray-300">
                            {new Date(p.date).toLocaleDateString('es-MX', { day: '2-digit', month: 'short', year: 'numeric' })}
                          </span>
                          <span className="text-sm text-white truncate">
                            {p.type === 'partial-payment' ? 'Pago parcial' : p.type === 'next-month-payment' ? 'Pago adelantado' : 'Renta mensual'}
                          </span>
                          <span className="text-sm text-gray-400 capitalize">{p.method || '-'}</span>
                          <span className="text-sm text-green-400 font-semibold text-right">${(p.amount || 0).toLocaleString()}</span>
                          <span className="text-xs text-gray-500 text-right">{p.receiptNumber || '-'}</span>
                        </div>
                      ))}
                      <div className="mt-4 pt-4 border-t border-[#252628] flex justify-between px-4">
                        <span className="text-gray-400 text-sm">Total pagos: {allPayments.length}</span>
                        <span className="text-green-400 font-semibold">
                          Total: ${allPayments.reduce((s, p) => s + (p.amount || 0), 0).toLocaleString()}
                        </span>
                      </div>
                    </div>
                  );
                })()}
              </div>
              <div className="p-4 border-t border-[#252628]">
                <button onClick={() => setShowPaymentHistoryModal(false)} className="w-full px-4 py-3 bg-[#35383d] hover:bg-[#45484d] text-white rounded-lg font-medium transition-colors">
                  Cerrar
                </button>
              </div>
            </div>
          </div>
        )}

        {/* Modal de Expediente del Arrendatario */}
        {showExpedienteModal && (
          <div className="fixed inset-0 bg-black/60 backdrop-blur-md flex items-center justify-center z-[60]">
            <div className="bg-[#1b1c20] rounded-2xl w-full max-w-3xl mx-4 shadow-2xl overflow-hidden max-h-[90vh] flex flex-col border border-[#252628]">
              <div className="p-6 border-b border-[#252628] flex items-center justify-between">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-xl bg-blue-500/20 flex items-center justify-center">
                    <i className="fas fa-folder-open text-blue-400"></i>
                  </div>
                  <div>
                    <h3 className="text-lg font-semibold text-white">Expediente del Arrendatario</h3>
                    <p className="text-xs text-gray-400">{apartment.name}</p>
                  </div>
                </div>
                <button onClick={() => setShowExpedienteModal(false)} className="text-gray-400 hover:text-white">
                  <i className="fas fa-times text-xl"></i>
                </button>
              </div>
              <div className="p-6 overflow-y-auto flex-1">
                {(() => {
                  const residentTenants = (apartment.residents || []).map(id => getTenantById(id)).filter(Boolean);
                  
                  if (residentTenants.length === 0) {
                    return (
                      <div className="text-center py-12">
                        <div className="w-16 h-16 rounded-full bg-gray-800 flex items-center justify-center mx-auto mb-4">
                          <i className="fas fa-user-slash text-gray-500 text-2xl"></i>
                        </div>
                        <p className="text-gray-400">Sin arrendatarios asignados</p>
                      </div>
                    );
                  }
                  
                  return residentTenants.map(tenant => (
                    <div key={tenant.id} className="space-y-5">
                      {/* Header */}
                      <div className="flex items-center gap-4 p-4 bg-[#252628] rounded-xl">
                        <div className="w-14 h-14 rounded-full bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center text-white text-xl font-bold shadow-lg">
                          {tenant.name?.charAt(0)?.toUpperCase() || 'T'}
                        </div>
                        <div>
                          <h4 className="text-white text-lg font-semibold">{tenant.name}</h4>
                          <p className="text-gray-400 text-sm">{tenant.email || 'Sin email'} • {tenant.phone || 'Sin teléfono'}</p>
                          <p className="text-gray-500 text-xs mt-1">{tenant.address || 'Sin dirección registrada'}</p>
                        </div>
                      </div>
                      
                      {/* Info Grid */}
                      <div className="grid grid-cols-2 gap-3">
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <p className="text-gray-500 text-xs uppercase tracking-wider mb-1">Renta Mensual</p>
                          <p className="text-white font-semibold text-lg">${(tenant.rentAmount || 0).toLocaleString()}</p>
                        </div>
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <p className="text-gray-500 text-xs uppercase tracking-wider mb-1">Estado de Pago</p>
                          <p className={`font-semibold text-lg ${tenant.paymentStatus === 'current' || tenant.paymentStatus === 'advanced' ? 'text-green-400' : 'text-red-400'}`}>
                            {tenant.paymentStatus === 'current' ? 'Al corriente' : tenant.paymentStatus === 'advanced' ? 'Adelantado' : 'Pendiente'}
                          </p>
                        </div>
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <p className="text-gray-500 text-xs uppercase tracking-wider mb-1">Depósito</p>
                          <p className="text-white font-semibold">{tenant.depositPaid ? `$${(tenant.depositAmount || 0).toLocaleString()} ✓` : 'No registrado'}</p>
                        </div>
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <p className="text-gray-500 text-xs uppercase tracking-wider mb-1">Fecha de Ingreso</p>
                          <p className="text-white font-semibold">{tenant.moveInDate ? new Date(tenant.moveInDate).toLocaleDateString('es-MX', { day: 'numeric', month: 'long', year: 'numeric' }) : 'No registrada'}</p>
                        </div>
                      </div>
                      
                      {/* Servicios */}
                      {(tenant.paysWater || tenant.paysElectricity) && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-bolt text-yellow-400"></i> Servicios
                          </h5>
                          <div className="grid grid-cols-2 gap-3">
                            {tenant.paysWater && (
                              <div className="flex items-center gap-2">
                                <i className="fas fa-tint text-blue-400"></i>
                                <span className="text-white text-sm">Agua: ${(tenant.waterAmount || 0).toLocaleString()}/mes</span>
                              </div>
                            )}
                            {tenant.paysElectricity && (
                              <div className="flex items-center gap-2">
                                <i className="fas fa-bolt text-yellow-400"></i>
                                <span className="text-white text-sm">Luz: ${(tenant.electricityAmount || 0).toLocaleString()}/mes</span>
                              </div>
                            )}
                          </div>
                        </div>
                      )}
                      
                      {/* Identificación */}
                      {tenant.identification && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-id-card text-purple-400"></i> Identificación
                          </h5>
                          <div className="grid grid-cols-2 gap-2 text-sm">
                            <div><span className="text-gray-500">Tipo:</span> <span className="text-white">{tenant.identification.type}</span></div>
                            <div><span className="text-gray-500">Número:</span> <span className="text-white font-mono">{tenant.identification.number}</span></div>
                            {tenant.identification.expiryDate && (
                              <div><span className="text-gray-500">Vigencia:</span> <span className="text-white">{new Date(tenant.identification.expiryDate).toLocaleDateString('es-MX')}</span></div>
                            )}
                          </div>
                        </div>
                      )}
                      
                      {/* Empleo */}
                      {tenant.employment && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-briefcase text-green-400"></i> Empleo
                          </h5>
                          <div className="grid grid-cols-2 gap-2 text-sm">
                            <div><span className="text-gray-500">Empresa:</span> <span className="text-white">{tenant.employment.company}</span></div>
                            <div><span className="text-gray-500">Puesto:</span> <span className="text-white">{tenant.employment.position}</span></div>
                            {tenant.employment.monthlySalary && (
                              <div><span className="text-gray-500">Ingreso:</span> <span className="text-white">${tenant.employment.monthlySalary.toLocaleString()}/mes</span></div>
                            )}
                            {tenant.employment.phone && (
                              <div><span className="text-gray-500">Tel. trabajo:</span> <span className="text-white">{tenant.employment.phone}</span></div>
                            )}
                          </div>
                        </div>
                      )}
                      
                      {/* Contacto de Emergencia */}
                      {tenant.emergencyContact && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-phone-alt text-red-400"></i> Contacto de Emergencia
                          </h5>
                          <div className="grid grid-cols-2 gap-2 text-sm">
                            <div><span className="text-gray-500">Nombre:</span> <span className="text-white">{tenant.emergencyContact.name}</span></div>
                            <div><span className="text-gray-500">Teléfono:</span> <span className="text-white">{tenant.emergencyContact.phone}</span></div>
                            <div><span className="text-gray-500">Parentesco:</span> <span className="text-white">{tenant.emergencyContact.relationship}</span></div>
                          </div>
                        </div>
                      )}
                      
                      {/* Fiador / Aval */}
                      {tenant.guarantor && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-user-shield text-orange-400"></i> Fiador / Aval
                          </h5>
                          <div className="grid grid-cols-2 gap-2 text-sm">
                            <div><span className="text-gray-500">Nombre:</span> <span className="text-white">{tenant.guarantor.name}</span></div>
                            <div><span className="text-gray-500">Teléfono:</span> <span className="text-white">{tenant.guarantor.phone}</span></div>
                            <div className="col-span-2"><span className="text-gray-500">Dirección:</span> <span className="text-white">{tenant.guarantor.address}</span></div>
                            {tenant.guarantor.identification && (
                              <div><span className="text-gray-500">ID:</span> <span className="text-white font-mono">{tenant.guarantor.identification}</span></div>
                            )}
                          </div>
                        </div>
                      )}
                      
                      {/* Referencias */}
                      {tenant.references && tenant.references.length > 0 && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-users text-cyan-400"></i> Referencias ({tenant.references.length})
                          </h5>
                          <div className="space-y-2">
                            {tenant.references.map((ref, i) => (
                              <div key={i} className="flex items-center justify-between text-sm p-2 bg-black/20 rounded-lg">
                                <div>
                                  <span className="text-white">{ref.name}</span>
                                  <span className="text-gray-500 ml-2">• {ref.relationship}</span>
                                </div>
                                <span className="text-gray-400">{ref.phone}</span>
                              </div>
                            ))}
                          </div>
                        </div>
                      )}
                      
                      {/* Vehículos */}
                      {tenant.vehicles && tenant.vehicles.length > 0 && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-car text-indigo-400"></i> Vehículos ({tenant.vehicles.length})
                          </h5>
                          {tenant.vehicles.map((v, i) => (
                            <div key={i} className="flex items-center justify-between text-sm p-2 bg-black/20 rounded-lg">
                              <span className="text-white">{v.year} {v.brand} {v.model} - {v.color}</span>
                              <span className="text-gray-400 font-mono">{v.plates}</span>
                            </div>
                          ))}
                        </div>
                      )}
                      
                      {/* Mascotas */}
                      {tenant.pets && tenant.pets.length > 0 && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-paw text-amber-400"></i> Mascotas ({tenant.pets.length})
                          </h5>
                          {tenant.pets.map((pet, i) => (
                            <div key={i} className="flex items-center justify-between text-sm p-2 bg-black/20 rounded-lg">
                              <span className="text-white">{pet.name} - {pet.breed} ({pet.type})</span>
                              <span className={`text-xs px-2 py-0.5 rounded-full ${pet.vaccinated ? 'bg-green-500/20 text-green-400' : 'bg-red-500/20 text-red-400'}`}>
                                {pet.vaccinated ? 'Vacunado' : 'Sin vacunas'}
                              </span>
                            </div>
                          ))}
                        </div>
                      )}
                      
                      {/* Notas */}
                      {tenant.notes && tenant.notes.length > 0 && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-sticky-note text-yellow-400"></i> Notas ({tenant.notes.length})
                          </h5>
                          <div className="space-y-2">
                            {tenant.notes.map((note, i) => (
                              <div key={i} className="p-3 bg-black/20 rounded-lg border-l-2 border-yellow-500/30">
                                <p className="text-white text-sm">{note.text}</p>
                                <p className="text-gray-500 text-xs mt-1">
                                  {note.createdBy} • {new Date(note.createdAt).toLocaleDateString('es-MX')}
                                </p>
                              </div>
                            ))}
                          </div>
                        </div>
                      )}

                      {/* Reportes */}
                      {tenant.reports && tenant.reports.length > 0 && (
                        <div className="p-4 bg-[#252628] rounded-xl">
                          <h5 className="text-gray-400 text-sm font-medium mb-3 flex items-center gap-2">
                            <i className="fas fa-exclamation-circle text-orange-400"></i> Reportes ({tenant.reports.length})
                          </h5>
                          <div className="space-y-2">
                            {tenant.reports.map((report, i) => {
                              const statusColors = {
                                resolved: 'bg-green-500/20 text-green-400',
                                'in-progress': 'bg-yellow-500/20 text-yellow-400',
                                pending: 'bg-red-500/20 text-red-400'
                              };
                              const statusLabels = {
                                resolved: 'Resuelto',
                                'in-progress': 'En progreso',
                                pending: 'Pendiente'
                              };
                              return (
                                <div key={i} className="p-3 bg-black/20 rounded-lg">
                                  <div className="flex items-center justify-between mb-1">
                                    <span className="text-white text-sm font-medium">{report.title}</span>
                                    <span className={`text-xs px-2 py-0.5 rounded-full ${statusColors[report.status] || statusColors.pending}`}>
                                      {statusLabels[report.status] || report.status}
                                    </span>
                                  </div>
                                  <p className="text-gray-400 text-xs">{report.description}</p>
                                  <p className="text-gray-500 text-xs mt-1">{new Date(report.createdAt).toLocaleDateString('es-MX')}</p>
                                </div>
                              );
                            })}
                          </div>
                        </div>
                      )}
                    </div>
                  ));
                })()}
              </div>
              <div className="p-4 border-t border-[#252628]">
                <button onClick={() => setShowExpedienteModal(false)} className="w-full px-4 py-3 bg-[#35383d] hover:bg-[#45484d] text-white rounded-lg font-medium transition-colors">
                  Cerrar
                </button>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  };

  if (editingApartment) {
    return (
      <AddApartmentPage 
        onCancel={() => {
          setEditingApartment(null);
          reloadData();
        }} 
        editData={editingApartment}
      />
    );
  }

  // Si hay departamento seleccionado, mostrar vista detalle
  if (selectedApartment) {
    return (
      <ApartmentDetailView 
        apartment={selectedApartment} 
        onClose={() => setSelectedApartment(null)} 
      />
    );
  }

  return (
    <div className="min-h-screen pt-6 pb-16">
      <div className="max-w-7xl mx-auto px-6">
        {/* Search bar, botones de vista y botón agregar */}
        <div className="max-w-5xl mx-auto mb-8 flex items-center gap-4">
          {/* Botones de vista */}
          <div className="flex rounded-lg p-1" style={{ background: 'var(--bg-secondary)' }}>
            <button
              onClick={() => setViewMode('grid')}
              className={`p-2 rounded-md transition-colors ${
                viewMode === 'grid' 
                  ? 'bg-blue-600 text-white' 
                  : 'text-gray-400 hover:text-white'
              }`}
              title="Vista cuadrícula"
            >
              <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
                <path d="M5 3a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2V5a2 2 0 00-2-2H5zM5 11a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2v-2a2 2 0 00-2-2H5zM11 5a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V5zM11 13a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
              </svg>
            </button>
            <button
              onClick={() => setViewMode('table')}
              className={`p-2 rounded-md transition-colors ${
                viewMode === 'table' 
                  ? 'bg-blue-600 text-white' 
                  : 'text-gray-400 hover:text-white'
              }`}
              title="Vista tabla"
            >
              <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
                <path fillRule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clipRule="evenodd" />
              </svg>
            </button>
          </div>

          {/* Searchbar */}
          <div className="relative flex-1">
            <div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none">
              <svg className="h-5 w-5 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
              </svg>
            </div>
            <input
              type="text"
              placeholder="Buscar departamento..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="search-bar-black"
            />
          </div>
          
          {/* Botón agregar */}
          <button 
            onClick={() => setCurrentPage('add-apartment')}
            className="btn-main px-4 py-3 flex items-center gap-2 whitespace-nowrap hover:bg-blue-600 transition-colors"
          >
            <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
            </svg>
            <span>Agregar Departamento</span>
          </button>
        </div>

        {/* Lista de departamentos */}
        {loading ? (
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-full">
            {[1, 2, 3, 4, 5, 6].map(i => (
              <SkeletonLoader key={i} type="card" className="h-64" />
            ))}
          </div>
        ) : filteredApartments.length === 0 ? (
          <div className="text-center py-20">
            <div className="w-20 h-20 mx-auto mb-4 rounded-full flex items-center justify-center" style={{ background: 'var(--bg-secondary)' }}>
              <i className="fas fa-building text-3xl text-gray-600"></i>
            </div>
            <h3 className="text-xl font-semibold text-white mb-2">
              {searchTerm ? 'No se encontraron departamentos' : 'No hay departamentos'}
            </h3>
            <p className="text-gray-400 mb-6">
              {searchTerm ? 'Intenta con otro término de búsqueda' : 'Agrega tu primer departamento para comenzar'}
            </p>
            {!searchTerm && (
              <button 
                onClick={() => setCurrentPage('add-apartment')}
                className="btn-main px-6 py-3 hover:bg-blue-600 transition-colors"
              >
                <i className="fas fa-plus mr-2"></i>
                Agregar Departamento
              </button>
            )}
          </div>
        ) : viewMode === 'grid' ? (
          // Vista Grid (sin fondo)
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            {filteredApartments.map(apartment => (
              <div 
                key={apartment.id}
                onClick={() => setSelectedApartment(apartment)}
                className="rounded-2xl p-4 hover:bg-white/5 transition-colors cursor-pointer group"
              >
                {/* Imagen o placeholder */}
                <div className="aspect-video rounded-xl mb-4 overflow-hidden" style={{ background: 'var(--bg-secondary)' }}>
                  {apartment.photos && apartment.photos.length > 0 ? (
                    <img 
                      src={apartment.photos[0]} 
                      alt={apartment.name}
                      className="w-full h-full object-cover group-hover:scale-105 transition-transform"
                    />
                  ) : (
                    <div className="w-full h-full flex items-center justify-center">
                      <i className="fas fa-building text-4xl text-gray-600"></i>
                    </div>
                  )}
                </div>

                {/* Info */}
                <div className="space-y-2">
                  <div className="flex items-start justify-between">
                    <h3 className="text-lg font-semibold text-white">{apartment.name}</h3>
                    <span className={`text-xs px-2 py-1 rounded-full ${
                      apartment.status === 'occupied' 
                        ? 'bg-green-500/20 text-green-400' 
                        : 'bg-gray-500/20 text-gray-400'
                    }`}>
                      {apartment.status === 'occupied' ? 'Ocupado' : 'Disponible'}
                    </span>
                  </div>
                  
                  {/* Ubicación (opcional) */}
                  {apartment.address && (
                    <div className="flex items-start gap-2 text-gray-400 text-sm">
                      <i className="fas fa-map-marker-alt mt-1 text-gray-500"></i>
                      <span className="line-clamp-2">{apartment.address}</span>
                    </div>
                  )}
                  
                  {/* Residentes */}
                  <div className="flex items-center gap-2 text-gray-400 text-sm pt-2">
                    <i className="fas fa-users text-gray-500"></i>
                    <span className="truncate">{getResidentNames(apartment.residents)}</span>
                  </div>
                </div>
              </div>
            ))}
          </div>
        ) : (
          // Vista Tabla (sin bordes)
          <div className="overflow-x-auto">
            <table className="w-full">
              <thead>
                <tr className="text-left text-gray-400 text-sm">
                  <th className="pb-4 font-medium">Departamento</th>
                  <th className="pb-4 font-medium">Ubicación</th>
                  <th className="pb-4 font-medium">Arrendatarios</th>
                  <th className="pb-4 font-medium">Estado</th>
                  <th className="pb-4 font-medium text-right">Acciones</th>
                </tr>
              </thead>
              <tbody>
                {filteredApartments.map(apartment => (
                  <tr 
                    key={apartment.id}
                    onClick={() => setSelectedApartment(apartment)}
                    className="hover:bg-white/5 cursor-pointer transition-colors"
                  >
                    <td className="py-4">
                      <div className="flex items-center gap-3">
                        <div className="w-12 h-12 rounded-lg overflow-hidden flex-shrink-0" style={{ background: 'var(--bg-secondary)' }}>
                          {apartment.photos && apartment.photos.length > 0 ? (
                            <img 
                              src={apartment.photos[0]} 
                              alt={apartment.name}
                              className="w-full h-full object-cover"
                            />
                          ) : (
                            <div className="w-full h-full flex items-center justify-center">
                              <i className="fas fa-building text-gray-600"></i>
                            </div>
                          )}
                        </div>
                        <span className="text-white font-medium">{apartment.name}</span>
                      </div>
                    </td>
                    <td className="py-4 text-gray-400 text-sm max-w-xs">
                      <span className="line-clamp-1">{apartment.address || '-'}</span>
                    </td>
                    <td className="py-4 text-gray-400 text-sm">
                      {getResidentNames(apartment.residents)}
                    </td>
                    <td className="py-4">
                      <span className={`text-xs px-2 py-1 rounded-full ${
                        apartment.status === 'occupied' 
                          ? 'bg-green-500/20 text-green-400' 
                          : 'bg-gray-500/20 text-gray-400'
                      }`}>
                        {apartment.status === 'occupied' ? 'Ocupado' : 'Disponible'}
                      </span>
                    </td>
                    <td className="py-4 text-right">
                      <button 
                        onClick={(e) => {
                          e.stopPropagation();
                          setSelectedApartment(apartment);
                        }}
                        className="text-gray-400 hover:text-white p-2 transition-colors"
                      >
                        <i className="fas fa-ellipsis-v"></i>
                      </button>
// ============================================
// UI COMPONENTS (Loaders, Skeletons, Search)
// ============================================

const SkeletonLoader = ({ type = 'text', className = '' }) => {
  // tipes: text, stat, chart, card, table-row
  if (type === 'stat') {
    return (
      <div className={`flex flex-col gap-2 ${className}`}>
        <div className="skeleton-loader h-8 w-1/2"></div>
        <div className="skeleton-loader h-4 w-1/3"></div>
      </div>
    );
  }
  if (type === 'chart') {
    return (
      <div className={`flex items-end gap-2 h-32 ${className}`}>
        {[40, 70, 45, 90, 65, 30, 80].map((h, i) => (
          <div key={i} className="skeleton-loader w-full rounded-t-md" style={{ height: `${h}%` }}></div>
        ))}
      </div>
    );
  }
  if (type === 'table-row') {
    return (
      <div className={`flex items-center justify-between py-3 border-b border-[var(--border-primary)] ${className}`}>
        <div className="flex items-center gap-3 w-1/2">
          <div className="skeleton-loader h-8 w-8 rounded-full"></div>
          <div className="skeleton-loader h-4 w-full"></div>
        </div>
        <div className="skeleton-loader h-4 w-1/4"></div>
      </div>
    );
  }
  if (type === 'card') {
    return (
      <div className={`p-4 rounded-xl border border-[var(--border-primary)] ${className}`}>
        <div className="skeleton-loader h-12 w-12 rounded-full mb-4"></div>
        <div className="skeleton-loader h-6 w-3/4 mb-2"></div>
        <div className="skeleton-loader h-4 w-1/2 mb-6"></div>
        <div className="skeleton-loader h-10 w-full rounded-lg"></div>
      </div>
    );
  }
  // Default 'text'
  return <div className={`skeleton-loader h-4 w-full ${className}`}></div>;
            <span>Agregar Departamento</span>
          </button>
        </div>

        {/* Lista de departamentos */}
        {loading ? (
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-full">
            {[1, 2, 3, 4, 5, 6].map(i => (
              <SkeletonLoader key={i} type="card" className="h-64" />
            ))}
          </div>
        ) : filteredApartments.length === 0 ? (
          <div className="text-center py-20">
            <div className="w-20 h-20 mx-auto mb-4 rounded-full flex items-center justify-center" style={{ background: 'var(--bg-secondary)' }}>
              <i className="fas fa-building text-3xl text-gray-600"></i>
            </div>
            <h3 className="text-xl font-semibold text-white mb-2">
              {searchTerm ? 'No se encontraron departamentos' : 'No hay departamentos'}
            </h3>
            <p className="text-gray-400 mb-6">
              {searchTerm ? 'Intenta con otro término de búsqueda' : 'Agrega tu primer departamento para comenzar'}
            </p>
            {!searchTerm && (
              <button 
                onClick={() => setCurrentPage('add-apartment')}
                className="btn-main px-6 py-3 hover:bg-blue-600 transition-colors"
              >
                <i className="fas fa-plus mr-2"></i>
                Agregar Departamento
              </button>
            )}
          </div>
        ) : viewMode === 'grid' ? (
          // Vista Grid (sin fondo)
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            {filteredApartments.map(apartment => (
              <div 
                key={apartment.id}
                onClick={() => setSelectedApartment(apartment)}
                className="rounded-2xl p-4 hover:bg-white/5 transition-colors cursor-pointer group"
              >
                {/* Imagen o placeholder */}
                <div className="aspect-video rounded-xl mb-4 overflow-hidden" style={{ background: 'var(--bg-secondary)' }}>
                  {apartment.photos && apartment.photos.length > 0 ? (
                    <img 
                      src={apartment.photos[0]} 
                      alt={apartment.name}
                      className="w-full h-full object-cover group-hover:scale-105 transition-transform"
                    />
                  ) : (
                    <div className="w-full h-full flex items-center justify-center">
                      <i className="fas fa-building text-4xl text-gray-600"></i>
                    </div>
                  )}
                </div>

                {/* Info */}
                <div className="space-y-2">
                  <div className="flex items-start justify-between">
                    <h3 className="text-lg font-semibold text-white">{apartment.name}</h3>
                    <span className={`text-xs px-2 py-1 rounded-full ${
                      apartment.status === 'occupied' 
                        ? 'bg-green-500/20 text-green-400' 
                        : 'bg-gray-500/20 text-gray-400'
                    }`}>
                      {apartment.status === 'occupied' ? 'Ocupado' : 'Disponible'}
                    </span>
                  </div>
                  
                  {/* Ubicación (opcional) */}
                  {apartment.address && (
                    <div className="flex items-start gap-2 text-gray-400 text-sm">
                      <i className="fas fa-map-marker-alt mt-1 text-gray-500"></i>
                      <span className="line-clamp-2">{apartment.address}</span>
                    </div>
                  )}
                  
                  {/* Residentes */}
                  <div className="flex items-center gap-2 text-gray-400 text-sm pt-2">
                    <i className="fas fa-users text-gray-500"></i>
                    <span className="truncate">{getResidentNames(apartment.residents)}</span>
                  </div>
                </div>
              </div>
            ))}
          </div>
        ) : (
          // Vista Tabla (sin bordes)
          <div className="overflow-x-auto">
            <table className="w-full">
              <thead>
                <tr className="text-left text-gray-400 text-sm">
                  <th className="pb-4 font-medium">Departamento</th>
                  <th className="pb-4 font-medium">Ubicación</th>
                  <th className="pb-4 font-medium">Arrendatarios</th>
                  <th className="pb-4 font-medium">Estado</th>
                  <th className="pb-4 font-medium text-right">Acciones</th>
                </tr>
              </thead>
              <tbody>
                {filteredApartments.map(apartment => (
                  <tr 
                    key={apartment.id}
                    onClick={() => setSelectedApartment(apartment)}
                    className="hover:bg-white/5 cursor-pointer transition-colors"
                  >
                    <td className="py-4">
                      <div className="flex items-center gap-3">
                        <div className="w-12 h-12 rounded-lg overflow-hidden flex-shrink-0" style={{ background: 'var(--bg-secondary)' }}>
                          {apartment.photos && apartment.photos.length > 0 ? (
                            <img 
                              src={apartment.photos[0]} 
                              alt={apartment.name}
                              className="w-full h-full object-cover"
                            />
                          ) : (
                            <div className="w-full h-full flex items-center justify-center">
                              <i className="fas fa-building text-gray-600"></i>
                            </div>
                          )}
                        </div>
                        <span className="text-white font-medium">{apartment.name}</span>
                      </div>
                    </td>
                    <td className="py-4 text-gray-400 text-sm max-w-xs">
                      <span className="line-clamp-1">{apartment.address || '-'}</span>
                    </td>
                    <td className="py-4 text-gray-400 text-sm">
                      {getResidentNames(apartment.residents)}
                    </td>
                    <td className="py-4">
                      <span className={`text-xs px-2 py-1 rounded-full ${
                        apartment.status === 'occupied' 
                          ? 'bg-green-500/20 text-green-400' 
                          : 'bg-gray-500/20 text-gray-400'
                      }`}>
                        {apartment.status === 'occupied' ? 'Ocupado' : 'Disponible'}
                      </span>
                    </td>
                    <td className="py-4 text-right">
                      <button 
                        onClick={(e) => {
                          e.stopPropagation();
                          setSelectedApartment(apartment);
                        }}
                        className="text-gray-400 hover:text-white p-2 transition-colors"
                      >
                        <i className="fas fa-ellipsis-v"></i>
                      </button>
// ============================================
// UI COMPONENTS (Loaders, Skeletons, Search)
// ============================================

const SkeletonLoader = ({ type = 'text', className = '' }) => {
  // tipes: text, stat, chart, card, table-row
  if (type === 'stat') {
    return (
      <div className={`flex flex-col gap-2 ${className}`}>
        <div className="skeleton-loader h-8 w-1/2"></div>
        <div className="skeleton-loader h-4 w-1/3"></div>
      </div>
    );
  }
  if (type === 'chart') {
    return (
      <div className={`flex items-end gap-2 h-32 ${className}`}>
        {[40, 70, 45, 90, 65, 30, 80].map((h, i) => (
          <div key={i} className="skeleton-loader w-full rounded-t-md" style={{ height: `${h}%` }}></div>
        ))}
      </div>
    );
  }
  if (type === 'table-row') {
    return (
      <div className={`flex items-center justify-between py-3 border-b border-[var(--border-primary)] ${className}`}>
        <div className="flex items-center gap-3 w-1/2">
          <div className="skeleton-loader h-8 w-8 rounded-full"></div>
          <div className="skeleton-loader h-4 w-full"></div>
        </div>
        <div className="skeleton-loader h-4 w-1/4"></div>
      </div>
    );
  }
  if (type === 'card') {
    return (
      <div className={`p-4 rounded-xl border border-[var(--border-primary)] ${className}`}>
        <div className="skeleton-loader h-12 w-12 rounded-full mb-4"></div>
        <div className="skeleton-loader h-6 w-3/4 mb-2"></div>
        <div className="skeleton-loader h-4 w-1/2 mb-6"></div>
        <div className="skeleton-loader h-10 w-full rounded-lg"></div>
      </div>
    );
  }
  // Default 'text'
  return <div className={`skeleton-loader h-4 w-full ${className}`}></div>;
};

const GreyLogoLoader = ({ text = 'CARGANDO...' }) => (
  <div className="w-full flex flex-col items-center justify-center py-12 opacity-50">
    <div className="skeleton-loader h-8 w-64 mb-4 rounded-lg"></div>
    <div className="skeleton-loader h-4 w-48 rounded-md"></div>
  </div>
);

  );
};

// ============================================
// SISTEMA DE CACHÉ OFFLINE - LocalStorage + IndexedDB
// ============================================

const CacheManager = {
  // Configuración
  CACHE_PREFIX: 'esperiency_cache_',
  CACHE_EXPIRY: 24 * 60 * 60 * 1000, // 24 horas por defecto
  PENDING_QUEUE_KEY: 'esperiency_pending_queue',
  
  // Estado de conexión
  isOnline: navigator.onLine,
  
  // Inicializar listeners de conexión
  init() {
    window.addEventListener('online', () => {
      this.isOnline = true;
      console.log('🌐 Conexión restaurada');
      this.showConnectionToast('online');
      this.processPendingQueue();
    });
    
    window.addEventListener('offline', () => {
      this.isOnline = false;
      console.log('📴 Sin conexión - Modo offline activado');
      this.showConnectionToast('offline');
    });
    
    // Verificar conexión real (no solo navigator.onLine)
    this.checkRealConnection();
  },
  
  // Verificar conexión real haciendo un ping
  async checkRealConnection() {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 5000);
      
      await fetch('https://www.google.com/favicon.ico', { 
        mode: 'no-cors',
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      this.isOnline = true;
    } catch (e) {
      this.isOnline = false;
    }
    return this.isOnline;
  },
  
  // Verificar si el API del servidor está funcionando
  async checkAPIStatus() {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 5000);
      
      // Intentar el health check del gateway
      const response = await fetch('http://localhost:3000/health', { 
        method: 'GET',
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      
      return response.ok;
    } catch (e) {
      console.log('API no disponible:', e.message);
      return false;
    }
  },
  
  // Mostrar toast de estado de conexión
  showConnectionToast(status) {
    if (typeof showToast === 'function') {
      if (status === 'online') {
        showToast('success', 'Conexión restaurada', 'Sincronizando datos...');
      } else {
        showToast('warning', 'Sin conexión', 'Trabajando en modo offline');
      }
    }
  },
  
  // Guardar en caché
  set(key, data, expiryMs = this.CACHE_EXPIRY) {
    try {
      const cacheItem = {
        data: data,
        timestamp: Date.now(),
        expiry: Date.now() + expiryMs
      };
      localStorage.setItem(this.CACHE_PREFIX + key, JSON.stringify(cacheItem));
      return true;
    } catch (e) {
      console.warn('Error guardando en caché:', e);
      // Si localStorage está lleno, limpiar caché antigua
      this.clearOldCache();
      try {
        const cacheItem = {
          data: data,
          timestamp: Date.now(),
          expiry: Date.now() + expiryMs
        };
        localStorage.setItem(this.CACHE_PREFIX + key, JSON.stringify(cacheItem));
        return true;
      } catch (e2) {
        return false;
      }
    }
  },
  
  // Obtener de caché
  get(key, ignoreExpiry = false) {
    try {
      const item = localStorage.getItem(this.CACHE_PREFIX + key);
      if (!item) return null;
      
      const cacheItem = JSON.parse(item);
      
      // Verificar expiración (a menos que estemos offline)
      if (!ignoreExpiry && !this.isOnline === false && Date.now() > cacheItem.expiry) {
        this.remove(key);
        return null;
      }
      
      return cacheItem.data;
    } catch (e) {
      return null;
    }
  },
  
  // Eliminar de caché
  remove(key) {
    try {
      localStorage.removeItem(this.CACHE_PREFIX + key);
    } catch (e) {}
  },
  
  // Limpiar caché antigua
  clearOldCache() {
    try {
      const now = Date.now();
      const keysToRemove = [];
      
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key && key.startsWith(this.CACHE_PREFIX)) {
          try {
            const item = JSON.parse(localStorage.getItem(key));
            if (item && item.expiry && now > item.expiry) {
              keysToRemove.push(key);
            }
          } catch (e) {}
        }
      }
      
      keysToRemove.forEach(key => localStorage.removeItem(key));
    } catch (e) {}
  },
  
  // Generar clave única para request
  generateKey(url, options = {}) {
    const method = options.method || 'GET';
    const body = options.body || '';
    return `${method}_${url}_${typeof body === 'string' ? body : JSON.stringify(body)}`.replace(/[^a-zA-Z0-9]/g, '_');
  },
  
  // Cola de operaciones pendientes (para cuando vuelva la conexión)
  addToPendingQueue(operation) {
    try {
      const queue = JSON.parse(localStorage.getItem(this.PENDING_QUEUE_KEY) || '[]');
      queue.push({
        ...operation,
        timestamp: Date.now(),
        id: Date.now() + '_' + Math.random().toString(36).substr(2, 9)
      });
      localStorage.setItem(this.PENDING_QUEUE_KEY, JSON.stringify(queue));
    } catch (e) {}
  },
  
  // Procesar cola pendiente cuando vuelva la conexión
  async processPendingQueue() {
    try {
      const queue = JSON.parse(localStorage.getItem(this.PENDING_QUEUE_KEY) || '[]');
      if (queue.length === 0) return;
      
      console.log(`📤 Procesando ${queue.length} operaciones pendientes...`);
      
      const newQueue = [];
      for (const operation of queue) {
        try {
          const response = await fetch(operation.url, operation.options);
          if (!response.ok) {
            // Si falla, mantener en cola solo si no es muy antiguo (max 7 días)
            if (Date.now() - operation.timestamp < 7 * 24 * 60 * 60 * 1000) {
              newQueue.push(operation);
            }
          }
        } catch (e) {
          // Si hay error de red, mantener en cola
          if (Date.now() - operation.timestamp < 7 * 24 * 60 * 60 * 1000) {
            newQueue.push(operation);
          }
        }
      }
      
      localStorage.setItem(this.PENDING_QUEUE_KEY, JSON.stringify(newQueue));
      
      if (newQueue.length < queue.length) {
        console.log(`✅ ${queue.length - newQueue.length} operaciones sincronizadas`);
      }
    } catch (e) {}
  },
  
  // Obtener estadísticas de caché
  getStats() {
    let count = 0;
    let size = 0;
    
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (key && key.startsWith(this.CACHE_PREFIX)) {
        count++;
        size += (localStorage.getItem(key) || '').length;
      }
    }
    
    return {
      itemCount: count,
      sizeBytes: size,
      sizeMB: (size / 1024 / 1024).toFixed(2),
      isOnline: this.isOnline
    };
  }
};

// Inicializar CacheManager
CacheManager.init();

// Función fetch con caché automático
const cachedFetch = async (url, options = {}, cacheOptions = {}) => {
  const {
    useCache = true,           // Usar caché
    cacheTime = 5 * 60 * 1000, // 5 minutos por defecto
    forceRefresh = false,      // Forzar actualización
    offlineFirst = false,      // Priorizar caché en offline
    queueIfOffline = false     // Encolar si es POST/PUT/DELETE y offline
  } = cacheOptions;
  
  const cacheKey = CacheManager.generateKey(url, options);
  const method = (options.method || 'GET').toUpperCase();
  
  // Para métodos que modifican datos
  if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {
    if (!CacheManager.isOnline && queueIfOffline) {
      // Encolar para cuando vuelva la conexión
      CacheManager.addToPendingQueue({ url, options });
      return { 
        ok: true, 
        queued: true, 
        json: async () => ({ success: true, queued: true, message: 'Operación guardada para sincronizar' })
      };
    }
  }
  
  // Intentar obtener de caché primero si estamos offline o offlineFirst
  if (useCache && (offlineFirst || !CacheManager.isOnline) && !forceRefresh) {
    const cached = CacheManager.get(cacheKey, !CacheManager.isOnline);
    if (cached) {
      console.log('📦 Usando datos en caché:', url);
      return {
        ok: true,
        fromCache: true,
        json: async () => cached,
        text: async () => JSON.stringify(cached)
      };
    }
  }
  
  // Si no hay conexión y no hay caché, retornar error controlado
  if (!CacheManager.isOnline) {
    const cached = CacheManager.get(cacheKey, true); // Intentar caché expirada
    if (cached) {
      console.log('📦 Usando caché expirada (offline):', url);
      return {
        ok: true,
        fromCache: true,
        stale: true,
        json: async () => cached,
        text: async () => JSON.stringify(cached)
      };
    }
    
    return {
      ok: false,
      offline: true,
      status: 0,
      json: async () => ({ success: false, error: 'Sin conexión', offline: true }),
      text: async () => 'Sin conexión a internet'
    };
  }
  
  // Hacer la petición real
  try {
    const response = await fetch(url, options);
    
    // Si es exitoso y es GET, guardar en caché
    if (response.ok && method === 'GET' && useCache) {
      const clonedResponse = response.clone();
      try {
        const data = await clonedResponse.json();
        CacheManager.set(cacheKey, data, cacheTime);
      } catch (e) {}
    }
    
    return response;
  } catch (error) {
    console.warn('Error en fetch, intentando caché:', error);
    
    // Si hay error de red, intentar caché
    const cached = CacheManager.get(cacheKey, true);
    if (cached) {
      return {
        ok: true,
        fromCache: true,
        stale: true,
        json: async () => cached,
        text: async () => JSON.stringify(cached)
      };
    }
    
    throw error;
  }
};

// Hacer disponible globalmente
window.CacheManager = CacheManager;
window.cachedFetch = cachedFetch;

// ============================================
// FIN SISTEMA DE CACHÉ
// ============================================
const parseJWT = (token) => {
  try {
    if (!token) {
      return null;
    }
    
    const base64Url = token.split('.')[1];
    if (!base64Url) {
      return null;
    }
    
    // Decodificar base64url a base64
    let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    while (base64.length % 4) {
      base64 += '=';
    }
    
    // Decodificar base64 de forma segura para UTF-8
    const jsonPayload = decodeURIComponent(
      atob(base64)
        .split('')
        .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
        .join('')
    );
    
    const parsed = JSON.parse(jsonPayload);
    
    return parsed;
  } catch (error) {
    console.error('❌ Error parsing JWT:', error);
    return null;
  }
};

const getJWTFromStorage = () => {

  const sessionAuthToken = sessionStorage.getItem('authToken');
  const authToken = localStorage.getItem('authToken');
  const sessionJWT = sessionStorage.getItem('jwt');
  const jwt = localStorage.getItem('jwt');

  const token = sessionAuthToken || sessionJWT || authToken || jwt;
  return token;
};

const fixUTF8String = (str) => {
  if (typeof str !== 'string') return str;
  try {
    const map = {
      'Ã±': 'ñ', 'Ã¡': 'á', 'Ã©': 'é', 'Ã­': 'í', 'Ã³': 'ó', 'Ãº': 'ú',
      'Ã ': 'à', 'Ã¨': 'è', 'Ã¬': 'ì', 'Ã²': 'ò', 'Ã¹': 'ù',
      'Ã¢': 'â', 'Ãª': 'ê', 'Ã®': 'î', 'Ã´': 'ô', 'Ã»': 'û',
      'Ã¤': 'ä', 'Ã«': 'ë', 'Ã¯': 'ï', 'Ã¶': 'ö', 'Ã¼': 'ü',
      'Ã§': 'ç', 'Ã	1': 'Ñ'
    };
    let out = str;
    Object.keys(map).forEach(k => {
      out = out.split(k).join(map[k]);
    });
    return out;
  } catch (e) {
    return str;
  }
};

const isValidJWT = (token) => {
  if (!token) return false;
  try {
    const payload = parseJWT(token);
    if (!payload) return false;
    if (payload.exp) {
      const now = Math.floor(Date.now() / 1000);
      if (payload.exp < now) return false;
    }
    return true;
  } catch (e) {
    return false;
  }
};

const clearAuthData = () => {
  try {
    localStorage.removeItem('authToken');
    sessionStorage.removeItem('authToken');
    localStorage.removeItem('jwt');
    sessionStorage.removeItem('jwt');
    localStorage.removeItem('organizationName');
    localStorage.removeItem('organizationId');
    localStorage.removeItem('organizationUuid');
    localStorage.removeItem('organizationCode');
    localStorage.removeItem('userData');
    sessionStorage.removeItem('userData');
    // Limpiar cookies de autenticación con TODAS las combinaciones posibles
    const hostname = window.location.hostname;
    const isProd = hostname.endsWith('esperiency.com');
    const secure = window.location.protocol === 'https:' ? ';Secure' : '';
    const exp = 'expires=Thu, 01 Jan 1970 00:00:00 UTC';
    const domains = [''];
    if (isProd) {
      domains.push(';domain=.esperiency.com');
      domains.push(`;domain=${hostname}`);
    }
    const cookieNames = ['authToken', 'isLoggedIn', 'userEmail', 'userData'];
    cookieNames.forEach(name => {
      domains.forEach(d => {
        document.cookie = `${name}=;${exp};path=/${d};SameSite=Lax${secure}`;
        document.cookie = `${name}=;${exp};path=/${d};`;
      });
    });
  } catch (e) {
    // ignore
  }
};

// ============================================
// VALIDACIÓN DE INTEGRIDAD DE SESIÓN
// Detecta datos corruptos o faltantes y solicita nuevo token
// ============================================
const validateSessionIntegrity = () => {
  try {
    const token = getJWTFromStorage();
    
    // 1. Verificar si hay token
    if (!token) {
      console.warn('⚠️ No hay token de sesión');
      return { valid: false, reason: 'NO_TOKEN' };
    }
    
    // 2. Verificar formato del token (debe tener 3 partes separadas por .)
    const tokenParts = token.split('.');
    if (tokenParts.length !== 3) {
      console.error('❌ Token corrupto: formato inválido');
      return { valid: false, reason: 'CORRUPT_TOKEN_FORMAT' };
    }
    
    // 3. Verificar que el payload sea decodificable
    const payload = parseJWT(token);
    if (!payload) {
      console.error('❌ Token corrupto: no se puede decodificar');
      return { valid: false, reason: 'CORRUPT_TOKEN_PAYLOAD' };
    }
    
    // 4. Verificar campos obligatorios en el payload
    // Normalizar UID de forma flexible para distintos proveedores de tokens (Firebase, OAuth, Custom)
    if (!payload.uid && (payload.sub || payload.user_id || payload.firebaseUid || payload.userId)) {
      payload.uid = payload.sub || payload.user_id || payload.firebaseUid || payload.userId;
    }
    
    const requiredFields = ['uid', 'email'];
    const missingFields = requiredFields.filter(field => !payload[field]);
    if (missingFields.length > 0) {
      console.error('❌ Token incompleto: faltan campos:', missingFields);
      return { valid: false, reason: 'MISSING_REQUIRED_FIELDS', missingFields };
    }
    
    // 5. Verificar expiración del token
    if (payload.exp) {
      const now = Math.floor(Date.now() / 1000);
      if (payload.exp < now) {
        console.warn('⚠️ Token expirado');
        return { valid: false, reason: 'TOKEN_EXPIRED' };
      }
    }
    
    // Helper para reconstruir y curar los datos del usuario a partir del token validado
    const rebuildUserDataFromPayload = (pay) => {
      try {
        const rebuilt = {
          uid: pay.uid,
          uuid: pay.uuid || null,
          email: pay.email,
          firstName: pay.firstName || '',
          lastName: pay.lastName || '',
          fullName: pay.fullName || `${pay.firstName || ''} ${pay.lastName || ''}`.trim() || 'Usuario',
          role: pay.role || 'user',
          emailVerified: pay.emailVerified || false,
          lastLogin: new Date().toISOString()
        };
        const persistent = !!localStorage.getItem('authToken');
        const storage = persistent ? localStorage : sessionStorage;
        storage.setItem('userData', JSON.stringify(rebuilt));
        
        // Sincronizar también en cookies para transiciones de subdominio
        const hostname = window.location.hostname;
        const domainStr = hostname.endsWith('esperiency.com') ? ';domain=.esperiency.com' : '';
        const secure = window.location.protocol === 'https:' ? ';Secure' : '';
        const days = persistent ? 30 : 1;
        const expires = new Date();
        expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
        document.cookie = `userData=${encodeURIComponent(JSON.stringify(rebuilt))};expires=${expires.toUTCString()};path=/${domainStr};SameSite=Lax${secure}`;
      } catch (e) {
        console.error('Error rebuilding userData from payload:', e);
      }
    };
    
    // 6. Verificar integridad de userData en storage
    const userDataStr = localStorage.getItem('userData') || sessionStorage.getItem('userData');
    if (userDataStr) {
      try {
        const userData = JSON.parse(userDataStr);
        // Verificar que userData no esté corrupto
        if (typeof userData !== 'object' || userData === null) {
          console.warn('⚠️ userData corrupto: no es un objeto. Reparando desde el token...');
          rebuildUserDataFromPayload(payload);
        } else if (userData.email && payload.email && userData.email.toLowerCase().trim() !== payload.email.toLowerCase().trim()) {
          console.warn('⚠️ Datos inconsistentes: email no coincide. Actualizando desde el token...');
          rebuildUserDataFromPayload(payload);
        }
      } catch (parseError) {
        console.warn('⚠️ userData corrupto: JSON inválido. Reparando desde el token...');
        rebuildUserDataFromPayload(payload);
      }
    } else {
      console.log('🔄 Inicializando userData faltante a partir del token...');
      rebuildUserDataFromPayload(payload);
    }
    
    // 7. Verificar consistencia de organizationId
    const storedOrgId = localStorage.getItem('organizationId');
    if (storedOrgId && payload.organizationId && storedOrgId !== payload.organizationId) {
      console.warn('⚠️ OrganizationId inconsistente, actualizando...');
      localStorage.setItem('organizationId', payload.organizationId);
    }
    
    console.log('✅ Integridad de sesión verificada');
    return { valid: true, payload };
    
  } catch (error) {
    console.error('❌ Error validando integridad de sesión:', error);
    return { valid: false, reason: 'VALIDATION_ERROR', error: error.message };
  }
};

// Función para manejar sesión inválida/corrupta
const handleInvalidSession = (reason, redirectToLogin = true) => {
  console.log(`🔄 Limpiando sesión inválida (${reason})...`);
  
  // Limpiar todos los datos de autenticación
  clearAuthData();
  
  // Mostrar notificación al usuario si está disponible
  if (typeof showToast === 'function') {
    const messages = {
      'NO_TOKEN': 'Sesión no encontrada. Por favor, inicia sesión.',
      'CORRUPT_TOKEN_FORMAT': 'Datos de sesión corruptos. Iniciando sesión nuevamente...',
      'CORRUPT_TOKEN_PAYLOAD': 'Error en datos de sesión. Iniciando sesión nuevamente...',
      'MISSING_REQUIRED_FIELDS': 'Información de usuario incompleta. Por favor, inicia sesión.',
      'TOKEN_EXPIRED': 'Tu sesión ha expirado. Por favor, inicia sesión nuevamente.',
      'CORRUPT_USER_DATA': 'Datos de usuario corruptos. Iniciando sesión nuevamente...',
      'CORRUPT_USER_DATA_JSON': 'Error en datos almacenados. Iniciando sesión nuevamente...',
      'DATA_MISMATCH': 'Inconsistencia en datos de sesión. Por favor, inicia sesión.',
      'VALIDATION_ERROR': 'Error de validación. Por favor, inicia sesión nuevamente.'
    };
    showToast('warning', 'Sesión inválida', messages[reason] || 'Por favor, inicia sesión nuevamente.');
  }
  
  // Redirigir al login después de un breve delay para mostrar el toast
  if (redirectToLogin) {
    setTimeout(() => {
      if (typeof Router !== 'undefined') {
        Router.navigate(Router.ROUTES.LOGIN, true);
      } else {
        window.location.href = './Login/index.html';
      }
    }, 1500);
  }
};

// Verificar sesión al cargar la aplicación
const initSessionValidation = () => {
  const validation = validateSessionIntegrity();
  
  if (!validation.valid) {
    handleInvalidSession(validation.reason);
    return false;
  }
  
  return true;
};

const hasValidOrganization = () => {
  try {
    const jwt = getJWTFromStorage();
    if (!jwt || !isValidJWT(jwt)) return false;
    const payload = parseJWT(jwt);
    if (!payload) return false;
    return !!(payload.organizationId || localStorage.getItem('organizationId'));
  } catch (e) {
    return false;
  }
};

const getOrganizationNameById = async (organizationId) => {
  try {
    if (!organizationId) {
      console.log('❌ getOrganizationNameById: No hay organizationId');
      return '';
    }
    
    // Usar Auth API
    const apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 
      ? 'http://localhost:3000' 
      : 'https://api.esperiency.com';
    
    const url = `${apiUrl}/api/org-name/${organizationId}`;
    console.log('🔍 Llamando a:', url);
    
    // Obtener token para autenticación
    const token = getJWTFromStorage();
    if (!token) {
      console.log('❌ No hay token de autenticación');
      return '';
    }
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      }
    });
    console.log('📡 Respuesta:', response.status, response.statusText);
    
    if (response && response.ok) {
      const data = await response.json();
      console.log('📦 Datos recibidos:', data);
      if (data && data.success && data.data) {
        return data.data.displayName || data.data.name || '';
      }
    }
    return '';
  } catch (e) {
    console.error('Error obteniendo nombre de organización:', e);
    return '';
  }
};

const getOrganizationInfo = async (orgId, orgCode) => {
  try {
    if (!orgId || !orgCode) return null;
    // Construir la URL de la API
    const apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 
      ? 'http://localhost:3000' 
      : 'https://api.esperiency.com';
    // Obtener token para autenticación
    const token = getJWTFromStorage();
    if (!token) {
      console.log('❌ No hay token de autenticación para getOrganizationInfo');
      return null;
    }
    
    let response;
    try {
      response = await fetch(`${apiUrl}/api/org-info`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({ orgId: orgId, orgCode: orgCode })
      });
    } catch (err) {
      console.error('Error en org-info fetch:', err);
      throw err;
    }
    
    if (response && response.ok) {
      const data = await response.json();
      if (data && data.success) {
        return data.organization;
      }
    }
    return null;
  } catch (e) {
    console.error('Error obteniendo información de organización:', e);
    return null;
  }
};

// Nueva función para obtener orgId desde Firestore y actualizar URL
const getOrgIdFromFirestore = async (jwt) => {
  try {
    const payload = parseJWT(jwt);
    if (!payload || !payload.organizationCode) {
      console.log('❌ No hay código de organización en el JWT');
      return null;
    }

    console.log('🔍 Obteniendo orgId desde Firestore para código:', payload.organizationCode);
    
    // Construir la URL de la API (Auth API)
    const apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 
      ? 'http://localhost:3000' 
      : 'https://api.esperiency.com';

    
    const response = await fetch(`${apiUrl}/api/get-org-id-by-code`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        organizationCode: payload.organizationCode
      })
    });
    
    if (response && response.ok) {
      const data = await response.json();
      if (data && data.success && data.orgId) {
        console.log('✅ OrgId encontrado en Firestore:', data.orgId);
        
        // Actualizar la URL con el orgId encontrado
        const currentUrl = new URL(window.location);
        currentUrl.searchParams.set(data.orgId, ''); // Agregar el orgId como parámetro
        
        // Actualizar la URL sin recargar la página
        window.history.replaceState({}, '', currentUrl);
        
        console.log('🔄 URL actualizada con orgId:', currentUrl.href);
        
        return data.orgId;
      }
    }
    
    console.log('❌ No se pudo obtener orgId desde Firestore');
    return null;
  } catch (error) {
    console.error('❌ Error obteniendo orgId desde Firestore:', error);
    return null;
  }
};

const getOrganizationNameByCode = async (orgCode) => {
  try {
    if (!orgCode) return { name: '', id: '' };

    // Construir la URL de la API
    const apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 
      ? 'http://localhost:3000' 
      : 'https://api.esperiency.com';

    const response = await fetch(`${apiUrl}/api/org-name-by-code/${orgCode}`);
    
    if (response && response.ok) {
      const data = await response.json();
      if (data && data.success) {
        return {
          name: data.organizationName || '',
          id: data.organizationId || ''
        };
      }
    }
    return { name: '', id: '' };
  } catch (e) {
    console.error('Error obteniendo nombre de organización por código:', e);
    return { name: '', id: '' };
  }
};

const getOrgIdFromUrl = () => {
  // Extraer orgId de la URL tipo /App/index.html?orgId
  const urlParams = new URLSearchParams(window.location.search);
  
  // Primero buscar en query parameters normales
  const orgIdParam = urlParams.get('orgId');
  if (orgIdParam) {
    return decodeURIComponent(orgIdParam);
  }
  
  // Si no hay parámetro orgId, usar el primer parámetro sin nombre (query string simple)
  const queryString = window.location.search;
  if (queryString && queryString.startsWith('?')) {
    const rawQuery = queryString.substring(1); // Quitar el ?
    // Si no contiene = entonces es solo el orgId
    if (!rawQuery.includes('=')) {
      return decodeURIComponent(rawQuery);
    }
  }
  
  return null;
};

const getMenuItems1 = (isCollapsed, setCurrentPage, currentPage) => [
  {
    title: "Inquilinos",
    icon: React.createElement('i', { className: `fas fa-users ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'inquilinos' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'inquilinos'
  },
  {
    title: "Administrar",
    icon: React.createElement('i', { className: `fas fa-cogs ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'administrar' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'administrar'
  },
  {
    title: "Analitica",
    icon: React.createElement('i', { className: `fas fa-chart-line ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'analitica' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'analitica'
  },
  {
    title: "Tareas",
    icon: React.createElement('i', { className: `fas fa-tasks ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'tareas' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'tareas'
  },
  {
    title: "Departamentos",
    icon: React.createElement('i', { className: `fas fa-building ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'departamentos' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'departamentos'
  },
  {
    title: "Mantenimiento",
    icon: React.createElement('i', { className: `fas fa-wrench ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'mantenimiento' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'mantenimiento'
  },
];

const getMenuItems2 = (isCollapsed, setCurrentPage, currentPage) => [
  {
    title: "Soporte",
    icon: React.createElement('i', { className: `fas fa-headset ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'soporte' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'soporte'
  },
  {
    title: "Mensajes",
    icon: React.createElement('i', { className: `fas fa-comments ${isCollapsed ? 'size-6' : 'size-5'} transition-colors duration-200 ${currentPage === 'chat' ? 'text-[#fae0d1]' : 'text-[#626367]'}` }),
    page: 'chat'
  },
];


const dashboardItems = [];


const rightSidebarItems = [];

const notifications = [];

const statusItems = [];

function SidebarLeft({ isCollapsed, setIsCollapsed, currentPage, setCurrentPage }) {

  const [organizationName, setOrganizationName] = React.useState('Cargando...');
  const [userInfo, setUserInfo] = React.useState({
    fullName: 'Cargando...',
    firstName: '',
    lastName: '',
    role: 'user',
    email: '',
    organizationRole: 'member'
  });
  
  const [userMenuOpen, setUserMenuOpen] = React.useState(false);
  

  const organizationLoaded = React.useRef(false);

  // Función para asociar usuario con organización (actualizar JWT)
  const updateUserOrganization = async (organizationId, organizationName, organizationCode) => {
    try {
      console.log('🔄 Asociando usuario con organización:', {
        organizationId,
        organizationName,
        organizationCode
      });
      
      const apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 
        ? 'http://localhost:3000' 
        : 'https://api.esperiency.com';

      
      const token = getJWTFromStorage();
      if (!token) {
        console.error('❌ No hay token JWT para actualizar');
        return;
      }
      
      // Decode token to get userId
      const payload = parseJWT(token);
      if (!payload) {
        console.error('❌ Error decodificando token');
        return;
      }
      
      const userId = payload.uid || payload.firebaseUid;
      if (!userId) {
        console.error('❌ No se encontró userId en el token');
        return;
      }
      
      const response = await fetch(`${apiUrl}/api/update-user-organization`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
          userId,
          organizationId,
          organizationName,
          organizationCode,
          token
        })
      });
      
      if (response.ok) {
        const result = await response.json();
        if (result.success && result.token) {
          // Actualizar el token en localStorage
          localStorage.setItem('authToken', result.token);
          console.log('✅ Usuario asociado con organización y JWT actualizado');
        } else {
          console.error('⚠️  Error en respuesta del servidor:', result);
        }
      } else {
        const errorText = await response.text();
        console.error('❌ Error asociando usuario con organización:', response.status, errorText);
      }
    } catch (error) {
      console.error('❌ Error en updateUserOrganization:', error);
    }
  };
  


  const getUserInitials = (firstName, lastName) => {
    const first = firstName?.charAt(0)?.toUpperCase() || '';
    const last = lastName?.charAt(0)?.toUpperCase() || '';
    return first + last || 'U';
  };

  const getRoleDisplayName = (role, organizationRole) => {
    // Primero verificar organizationRole (rol dentro de la organización)
    if (organizationRole === 'admin' || organizationRole === 'administrador') return 'Administrador';
    if (organizationRole === 'owner' || organizationRole === 'propietario') return 'Propietario';
    if (organizationRole === 'manager' || organizationRole === 'gerente') return 'Gerente';
    
    // Luego verificar role (rol global del usuario)
    if (role === 'admin' || role === 'administrador') return 'Administrador';
    if (role === 'superadmin') return 'Super Admin';
    
    // Roles de usuario normal
    if (organizationRole === 'member' || organizationRole === 'miembro') return 'Miembro';
    if (organizationRole === 'usuario' || role === 'user' || role === 'usuario') return 'Usuario';
    
    return 'Usuario';
  };

  const toggleUserMenu = (e) => {
    e.stopPropagation();
    setUserMenuOpen(!userMenuOpen);
  };

  const toggleSidebar = () => {
    setIsCollapsed(!isCollapsed);
    setUserMenuOpen(false);
  };

  const handleMenuItemClick = (action) => {
    setUserMenuOpen(false);
    switch (action) {
      case 'personalizar':
        setCurrentPage('dashboard');
        // Small delay to ensure DashboardWidgets is mounted before calling
        setTimeout(() => {
          if (window.enterCustomizeMode) window.enterCustomizeMode();
        }, 150);
        break;
      case 'configuracion':
        setCurrentPage('configuracion');
        break;
      case 'cerrar-sesion':
        clearAuthData();
        if (typeof Router !== 'undefined') {
          Router.logout();
        } else {
          window.location.href = './Login/index.html';
        }
        break;
    }
  };

  React.useEffect(() => {
    const handleClickOutside = () => {
      if (userMenuOpen) {
        setUserMenuOpen(false);
      }
    };

    if (userMenuOpen) {
      document.addEventListener('click', handleClickOutside);
    }

    return () => {
      document.removeEventListener('click', handleClickOutside);
    };
  }, [userMenuOpen]);

  React.useEffect(() => {
    // ============================================
    // VALIDACIÓN DE INTEGRIDAD DE SESIÓN
    // ============================================
    const sessionValidation = validateSessionIntegrity();
    
    if (!sessionValidation.valid) {
      // Si la sesión es inválida/corrupta, limpiar todo y redirigir
      handleInvalidSession(sessionValidation.reason);
      setOrganizationName('Sesión inválida');
      setUserInfo({
        fullName: 'Usuario no autenticado',
        firstName: '',
        lastName: '',
        role: 'guest',
        email: '',
        organizationRole: 'none'
      });
      return;
    }
    
    const jwtToken = getJWTFromStorage();
    const payload = sessionValidation.payload || parseJWT(jwtToken);
    
    if (payload) {
      const firstName = fixUTF8String(payload?.firstName || '');
      const lastName = fixUTF8String(payload?.lastName || '');
      const fullName = fixUTF8String(payload?.fullName) || `${firstName} ${lastName}`.trim() || 'Usuario';

      console.log('👤 Datos de usuario desde JWT:', {
        role: payload?.role,
        organizationRole: payload?.organizationRole,
        email: payload?.email
      });
      
      setUserInfo({
        fullName: fullName,
        firstName: firstName,
        lastName: lastName,
        role: payload?.role || 'user',
        email: payload?.email || '',
        organizationRole: payload?.organizationRole || 'member'
      });
      const orgName = localStorage.getItem('organizationName') || payload?.organizationName || null;
      if (orgName) {
        setOrganizationName(orgName);
      }
    }
    if (!hasValidOrganization()) {
      setOrganizationName('Sin organización configurada');
    }
    
    // ============================================
    // CARGAR ORGANIZACIÓN DESDE JWT (SEGURO)
    // La información de organización viene encriptada en el token
    // ============================================
    
    let organizationId = null;
    let organizationCode = null;
    
    // Prioridad 1: Obtener del payload del JWT (más seguro)
    if (payload) {
      organizationId = payload?.organizationId || null;
      organizationCode = payload?.organizationCode || null;
    }
    
    // Prioridad 2: Fallback a localStorage (datos previamente guardados)
    if (!organizationId) {
      organizationId = localStorage.getItem('organizationId');
    }
    if (!organizationCode) {
      organizationCode = localStorage.getItem('organizationCode');
    }
    
    console.log('🔐 Datos de organización desde JWT:', {
      organizationId,
      organizationCode,
      source: payload?.organizationId ? 'JWT' : 'localStorage'
    });
    
    // Función para procesar la información de organización
    const processOrganizationInfo = async (orgId, orgCode) => {
      if (!orgId || organizationLoaded.current) return;
      
      organizationLoaded.current = true;
      console.log('📡 Obteniendo información completa de organización...');
      
      // Siempre configurar variables globales con datos del JWT como mínimo
      window.currentOrganizationId = orgId;
      if (orgCode) window.currentOrganizationCode = orgCode;
      localStorage.setItem('organizationId', orgId);
      
      try {
        // Si tenemos código, usar el método completo
        if (orgCode) {
          const orgInfo = await getOrganizationInfo(orgId, orgCode);
          if (orgInfo && orgInfo.name) {
            setOrganizationName(orgInfo.name);
            localStorage.setItem('organizationId', orgInfo.id);
            localStorage.setItem('organizationName', orgInfo.name);
            localStorage.setItem('organizationCode', orgInfo.code);
            localStorage.setItem('organizationUuid', orgInfo.uuid);
            
            // Variables globales para otros componentes
            window.currentOrganizationId = orgInfo.id;
            window.currentOrganizationCode = orgInfo.code;
            window.currentOrganizationName = orgInfo.name;
            window.currentOrganizationUuid = orgInfo.uuid;
            
            console.log('✅ Información de organización cargada:', orgInfo);
            
            // 🔄 Asociar usuario con la organización (actualizar JWT)
            updateUserOrganization(orgInfo.id, orgInfo.name, orgInfo.code);
            return; // ✅ Salir después de procesar exitosamente
          } else {
            // API no encontró la org, pero mantenemos el orgId del JWT
            const fallbackName = payload?.organizationName || localStorage.getItem('organizationName') || 'Mi Organización';
            setOrganizationName(fallbackName);
            console.log('⚠️ org-info no disponible, usando datos del JWT:', { orgId, fallbackName });
            return;
          }
        }
        
        // Fallback: obtener solo por ID
        const orgName = await getOrganizationNameById(orgId);
        if (orgName) {
          setOrganizationName(orgName);
          localStorage.setItem('organizationId', orgId);
          localStorage.setItem('organizationName', orgName);
          
          // Variables globales para otros componentes
          window.currentOrganizationId = orgId;
          window.currentOrganizationName = orgName;
          
          console.log('✅ Organización cargada (solo por ID):', { orgId, orgName });
        } else {
          setOrganizationName('Organización no encontrada');
        }
      } catch (error) {
        console.error('Error obteniendo información de organización:', error);
        // Usar datos del JWT como fallback (window.currentOrganizationId ya fue configurado arriba)
        const fallbackName = payload?.organizationName || localStorage.getItem('organizationName') || 'Mi Organización';
        setOrganizationName(fallbackName);
        console.log('⚠️ Usando datos del JWT como fallback:', { orgId, fallbackName });
      }
    };
    
    // Procesar organización si tenemos datos
    if (organizationId) {
      processOrganizationInfo(organizationId, organizationCode);
    } else {
      // Si no hay orgId en JWT ni localStorage, intentar desde Firestore
      const loadOrgIdFromFirestore = async () => {
        const jwt = getJWTFromStorage();
        if (jwt) {
          console.log('🔄 No hay orgId en JWT, consultando Firestore...');
          const orgIdFromFirestore = await getOrgIdFromFirestore(jwt);
          if (orgIdFromFirestore) {
            processOrganizationInfo(orgIdFromFirestore, null);
          }
        }
      };
      loadOrgIdFromFirestore();
    }
  }, []);


  
  return (
    <div className={`fixed left-0 inset-y-0 flex-col p-4 hidden xl:flex overflow-x-hidden overflow-y-auto transition-all duration-300 ease-in-out ${isCollapsed ? 'w-16' : 'w-64'}`} style={{ background: 'var(--bg-body)' }}>
      <div className="shrink-0 flex items-center justify-between">
        {!isCollapsed && <div className="text-white font-semibold text-lg truncate">{organizationName}</div>}
        <div 
          className="size-8 rounded-full grid place-items-center border-2 border-[#252628] text-white cursor-pointer hover:bg-[#252628] transition-colors"
          onClick={toggleSidebar}
        >
          <svg className={`size-5 transition-transform duration-300 ${isCollapsed ? 'rotate-180' : ''}`} strokeWidth={3} viewBox="0 0 24 24" fill="none" stroke="currentColor">
            <path d="m15 18-6-6 6-6"/>
          </svg>
        </div>
      </div>
      
      <div className="shrink-0 relative">
        <div 
          className={`flex items-center p-2 mt-3 transition-colors ${
            isCollapsed 
              ? 'justify-center' 
              : 'bg-[#1b1c20] rounded-md hover:bg-[#252628] cursor-pointer'
          }`}
          onClick={isCollapsed ? undefined : toggleUserMenu}
        >
          <div 
            className={`size-9 rounded-full flex items-center justify-center font-semibold text-sm transition-all duration-300 flex-shrink-0 ${
              isCollapsed ? 'cursor-pointer' : ''
            }`}
            style={{
              background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
              color: '#ffffff'
            }}
          >
            {getUserInitials(userInfo.firstName, userInfo.lastName)}
          </div>
          {!isCollapsed && (
            <>
              <div className="ml-2">
                <div className="font-semibold text-white cursor-pointer select-none">{userInfo.fullName}</div>
                <div className="text-[#7a7d82] cursor-pointer select-none">{getRoleDisplayName(userInfo.role, userInfo.organizationRole)}</div>
              </div>
              <svg className="size-4 ml-auto text-[#7a7d82] cursor-pointer" strokeWidth={3} viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <circle cx="12" cy="12" r="1"/>
                <circle cx="12" cy="5" r="1"/>
                <circle cx="12" cy="19" r="1"/>
              </svg>
            </>
          )}
        </div>


        {userMenuOpen && !isCollapsed && (
          <div 
            className="absolute top-full left-0 w-full mt-2 bg-[#1b1c20] rounded-md shadow-lg border border-[#252628] py-1 z-50 animate-slideDown"
            style={{
              animation: 'slideDown 0.2s ease-out forwards',
              transformOrigin: 'top'
            }}
          >
            <button
              onClick={() => handleMenuItemClick('personalizar')}
              className="w-full flex items-center px-3 py-2 text-sm text-white hover:bg-gray-600 hover:text-white transition-colors"
            >
              <i className="fas fa-palette w-4 mr-3"></i>
              Personalizar
            </button>
            <button
              onClick={() => handleMenuItemClick('configuracion')}
              className="w-full flex items-center px-3 py-2 text-sm text-white hover:bg-gray-600 hover:text-white transition-colors"
            >
              <i className="fas fa-cog w-4 mr-3"></i>
              Configuración
            </button>
            <button
              onClick={() => handleMenuItemClick('cerrar-sesion')}
              className="w-full flex items-center px-3 py-2 text-sm text-white hover:bg-red-500 hover:text-white transition-colors"
            >
              <i className="fas fa-sign-out-alt w-4 mr-3"></i>
              Cerrar sesión
            </button>
          </div>
        )}
      </div>

      <div className="shrink-0 py-2 mt-3 border-t-2 border-t-zinc-800">
        <button 
          onClick={() => setCurrentPage('dashboard')}
          className={`w-full flex items-center p-1.5 rounded-lg transition-all duration-200 group/item ${
            isCollapsed ? 'justify-center px-0 py-2' : ''
          } ${
            currentPage === 'dashboard'
              ? 'bg-white/[0.06]'
              : 'hover:bg-white/[0.04]'
          }`}
          style={currentPage === 'dashboard' && !isCollapsed ? { boxShadow: 'inset 2px 0 0 var(--accent)' } : {}}
        >
          <div className={`${isCollapsed ? 'flex items-center justify-center w-full' : 'ml-1'} transition-transform duration-300 group-hover/item:scale-110 group-active/item:scale-95`}>
            <svg className={`${isCollapsed ? 'size-6' : 'size-5'} shrink-0 transition-all duration-300 ${currentPage === 'dashboard' ? 'text-[#fae0d1]' : 'text-[#626367] group-hover/item:text-[#fae0d1]/70'}`} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <rect width="7" height="9" x="3" y="3" rx="1"/>
              <rect width="7" height="5" x="14" y="3" rx="1"/>
              <rect width="7" height="9" x="14" y="12" rx="1"/>
              <rect width="7" height="5" x="3" y="16" rx="1"/>
            </svg>
          </div>
          {!isCollapsed && <div className={`ml-2 transition-all duration-300 group-hover/item:translate-x-0.5 ${currentPage === 'dashboard' ? 'text-white font-medium' : 'text-[#c0c4cd] group-hover/item:text-white'}`}>Dashboard</div>}
        </button>
      </div>

      <div className="shrink-0 flex flex-col py-1 gap-0.5 border-t-2 border-t-zinc-800">
        {getMenuItems1(isCollapsed, setCurrentPage, currentPage).map(({ title, icon, count, page }, idx) => (
          <button
            onClick={() => setCurrentPage(page)}
            className={`flex items-center p-1.5 rounded-lg transition-all duration-200 group/item ${
              isCollapsed ? 'justify-center px-0 py-2' : ''
            } ${
              currentPage === page
                ? 'bg-white/[0.06]'
                : 'hover:bg-white/[0.04]'
            }`}
            style={{
              ...(currentPage === page && !isCollapsed ? { boxShadow: 'inset 2px 0 0 var(--accent)' } : {}),
              animationDelay: `${idx * 40}ms`
            }}
            key={idx}
          >
            <div className={`${isCollapsed ? 'flex items-center justify-center w-full' : 'ml-1'} transition-transform duration-300 group-hover/item:scale-110 group-active/item:scale-95`}>
              {icon}
            </div>
            {!isCollapsed && (
              <>
                <div className={`ml-2 transition-all duration-300 group-hover/item:translate-x-0.5 ${currentPage === page ? 'text-white font-medium' : 'text-[#c0c4cd] group-hover/item:text-white'}`}>{title}</div>
                {count > 0 && (
                  <div className="grid place-items-center size-6 bg-[#fae0d1] text-black rounded-md ml-auto text-sm font-semibold">
                    {count}
                  </div>
                )}
              </>
            )}
          </button>
        ))}
      </div>

      <div className="grow flex flex-col py-1 mt-1 gap-0.5 border-t-2 border-t-zinc-800">
        {getMenuItems2(isCollapsed, setCurrentPage, currentPage).map(({ title, icon, page }, idx) => (
          <button
            onClick={() => setCurrentPage(page)}
            className={`flex items-center p-1.5 rounded-lg transition-all duration-200 group/item ${
              isCollapsed ? 'justify-center px-0 py-2' : ''
            } ${
              currentPage === page
                ? 'bg-white/[0.06]'
                : 'hover:bg-white/[0.04]'
            }`}
            style={currentPage === page && !isCollapsed ? { boxShadow: 'inset 2px 0 0 var(--accent)' } : {}}
            key={idx}
          >
            <div className={`${isCollapsed ? 'flex items-center justify-center w-full' : 'ml-1'} transition-transform duration-300 group-hover/item:scale-110 group-active/item:scale-95`}>
              {icon}
            </div>
            {!isCollapsed && <div className={`ml-2 transition-all duration-300 group-hover/item:translate-x-0.5 ${currentPage === page ? 'text-white font-medium' : 'text-[#c0c4cd] group-hover/item:text-white'}`}>{title}</div>}
          </button>
        ))}
      </div>


    </div>
  );
}

function Dashboard() {
  return (
    <>
      <div className="px-4">
        <div className="text-lg font-semibold text-white">Dashboard</div>
        <div className="p-1 bg-[#000000] rounded-md mt-1">
          <div className="grid grid-cols-3 gap-2">
            {dashboardItems.map(({ title, Icon }, idx) => (
              <div
                className={`py-2 rounded-md flex items-center justify-center space-x-2 ${
                  idx === 0 ? "bg-[#35383d] text-white" : "text-[#575757] hover:bg-[#1a1a1a]"
                }`}
                key={idx}
              >
                <Icon />
                <div className="text-sm">{title}</div>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="flex items-center mt-2 px-4">
        <svg className="size-5 text-[#6e7176]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
          <circle cx="9" cy="7" r="4"/>
          <path d="M22 21v-2a4 4 0 0 0-3-3.87"/>
          <path d="M16 3.13a4 4 0 0 1 0 7.75"/>
        </svg>
        <div className="ml-2 text-base font-semibold text-white">Deudores</div>
        <div className="inline-flex items-center ml-auto space-x-3">
          <div className="bg-[#35383d] px-2 py-0.5 rounded-md text-white text-sm">All</div>
          <div className="bg-[#35383d] px-2 py-0.5 rounded-md text-white text-sm">Todos los deudores</div>
        </div>
      </div>
      <CampaignSlider />
    </>
  );
}

function CampaignSlider() {
  React.useEffect(() => {
    if (typeof Swiper !== 'undefined') {
      new Swiper(".mySwiper", {
        slidesPerView: "auto",
        spaceBetween: 16,
        slidesOffsetBefore: 16,
        slidesOffsetAfter: 40,
      });
    }
  }, []);

  return (
    <div className="mt-3 relative">
      <div className="swiper mySwiper">
        <div className="swiper-wrapper">
          {campaigns.map(({ title, redemptions, remaining, color }, idx) => (
            <div
              className="swiper-slide rounded-md p-3 select-none cursor-pointer"
              key={idx}
              style={{ background: color, height: '105px', width: '220px' }}
            >
              <div className="flex items-center border-b-2 border-b-[#6464648c] pb-2">
                <div className="size-3 rounded-full bg-[#37363e]"></div>
                <div className="ml-2 font-semibold text-[#37363e]">{title}</div>
                <svg className="size-5 ml-auto text-[#555]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                  <circle cx="12" cy="12" r="1"/>
                  <circle cx="19" cy="12" r="1"/>
                  <circle cx="5" cy="12" r="1"/>
                </svg>
              </div>

              <div className="grid grid-cols-2 mt-3">
                <div>
                  <div className="text-[#555]">Remaining</div>
                  <div className="flex items-center space-x-2">
                    <svg className="size-4 text-[#555]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                      <circle cx="12" cy="12" r="10"/>
                      <polyline points="12,6 12,12 16,14"/>
                    </svg>
                    <div className="text-[#37363e] font-semibold">{remaining}</div>
                  </div>
                </div>

                <div>
                  <div className="text-[#555]">Reportes</div>
                  <div className="flex items-center space-x-2">
                    <svg className="size-4 text-[#555]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                      <path d="M3 3v18h18" />
                      <path d="M18.7 8l-5.1 5.2-2.8-2.7L7 14.3" />
                    </svg>
                    <div className="text-[#37363e] font-semibold">{redemptions}</div>
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>

      <div
        className="absolute inset-y-0 w-4 z-10"
        style={{
          background: "linear-gradient(90deg, #18181B 0%, rgba(24, 24, 27, 0) 100%)",
          left: "0px",
        }}
      ></div>
      <div
        className="absolute inset-y-0 w-20 z-10"
        style={{
          background: "linear-gradient(90deg, rgba(24, 24, 27, 0) 0%, #18181B 100%)",
          right: "0px",
        }}
      ></div>

      <button
        className="size-9 absolute rounded-full z-20 bg-white grid place-items-center"
        style={{ right: "8px", top: "32px" }}
      >
        <svg className="size-5 text-zinc-900" strokeWidth={3} viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <path d="m9 18 6-6-6-6"/>
        </svg>
      </button>
    </div>
  );
}
const paymentData = [];

const ingresosData = [];

const recentPayments = [];

// Datos de campañas/deudores (vacío - se llenará con datos reales)
const campaigns = [];

// ============================================
// WIDGETS DEL DASHBOARD - DISEÑO INTUITIVO
// ============================================

function WelcomeWidget() {
  const [currentTime, setCurrentTime] = React.useState(new Date());
  const [greeting, setGreeting] = React.useState('');
  const [userName, setUserName] = React.useState('');
  
  React.useEffect(() => {
    const timer = setInterval(() => setCurrentTime(new Date()), 1000);
    return () => clearInterval(timer);
  }, []);
  
  React.useEffect(() => {
    const hour = currentTime.getHours();
    if (hour < 12) setGreeting('Buenos días');
    else if (hour < 18) setGreeting('Buenas tardes');
    else setGreeting('Buenas noches');
  }, [currentTime]);
  
  React.useEffect(() => {
    // Obtener nombre del usuario desde JWT
    const token = getJWTFromStorage();
    if (token) {
      const payload = parseJWT(token);
      if (payload) {
        const firstName = fixUTF8String(payload?.firstName || '');
        setUserName(firstName);
      }
    }
  }, []);
  
  const formatDate = () => {
    const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
    return currentTime.toLocaleDateString('es-ES', options);
  };
  
  return (
    <div className="rounded-2xl p-7 col-span-full hover-lift border border-white/[0.04]" style={{ background: 'linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 100%)', backdropFilter: 'blur(20px)', boxShadow: 'var(--shadow)' }}>
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-3xl font-bold text-white mb-1">
            {greeting}{userName ? `, ${userName}` : ''} 👋
          </h1>
          <p className="text-gray-400 capitalize">{formatDate()}</p>
        </div>
        <div className="text-right">
          <div className="text-4xl font-bold text-[#fae0d1] tabular-nums">
            {currentTime.toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true })}
          </div>
          <div className="text-gray-500 text-sm">Hora local</div>
        </div>
      </div>
    </div>
  );
}

function QuickStatsWidget({ setCurrentPage }) {
  const [stats, setStats] = React.useState([
    { 
      title: 'Total Inquilinos', 
      value: '...', 
      icon: 'fas fa-users',
      bgColor: 'bg-blue-500/10',
      textColor: 'text-blue-400',
      loading: true,
      page: 'inquilinos'
    },
    { 
      title: 'Pagos al Día', 
      value: '...', 
      icon: 'fas fa-check-circle',
      bgColor: 'bg-green-500/10',
      textColor: 'text-green-400',
      loading: true,
      page: 'inquilinos'
    },
    { 
      title: 'Pendientes', 
      value: '...', 
      icon: 'fas fa-clock',
      bgColor: 'bg-orange-500/10',
      textColor: 'text-orange-400',
      loading: true,
      page: 'inquilinos'
    },
    { 
      title: 'Ingresos Mes', 
      value: '...', 
      icon: 'fas fa-dollar-sign',
      bgColor: 'bg-purple-500/10',
      textColor: 'text-purple-400',
      loading: true,
      page: 'analitica'
    }
  ]);
  
  React.useEffect(() => {
    const fetchStats = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) {
          setStats(prev => prev.map(s => ({ ...s, value: '0', loading: false })));
          return;
        }
        
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
          }
        }, { cacheTime: 5 * 60 * 1000 }); // Caché de 5 minutos
        
        if (response.ok) {
          const result = await response.json();
          const tenants = result.data || [];
          
          // Calcular estadísticas
          const activeTenants = tenants.filter(t => t.status !== 'archived');
          const totalTenants = activeTenants.length;
          const paidTenants = activeTenants.filter(t => t.paymentStatus === 'current' || t.paymentStatus === 'advanced').length;
          const pendingTenants = activeTenants.filter(t => t.paymentStatus === 'overdue').length;
          const monthlyIncome = activeTenants.reduce((sum, t) => sum + (parseFloat(t.rentAmount) || 0), 0);
          
          setStats([
            { 
              title: 'Total Inquilinos', 
              value: totalTenants.toString(), 
              icon: 'fas fa-users',
              bgColor: 'bg-blue-500/10',
              textColor: 'text-blue-400',
              loading: false,
              page: 'inquilinos'
            },
            { 
              title: 'Pagos al Día', 
              value: paidTenants.toString(), 
              icon: 'fas fa-check-circle',
              bgColor: 'bg-green-500/10',
              textColor: 'text-green-400',
              loading: false,
              page: 'inquilinos'
            },
            { 
              title: 'Pendientes', 
              value: pendingTenants.toString(), 
              icon: 'fas fa-clock',
              bgColor: 'bg-orange-500/10',
              textColor: 'text-orange-400',
              loading: false,
              page: 'inquilinos'
            },
            { 
              title: 'Ingresos Mes', 
              value: `$${monthlyIncome.toLocaleString('es-MX')}`, 
              icon: 'fas fa-dollar-sign',
              bgColor: 'bg-purple-500/10',
              textColor: 'text-purple-400',
              loading: false,
              page: 'analitica'
            }
          ]);
        }
      } catch (error) {
        console.error('Error fetching stats:', error);
        setStats(prev => prev.map(s => ({ ...s, value: '0', loading: false })));
      }
    };
    
    fetchStats();
    // Actualizar cada 30 segundos
    const interval = setInterval(fetchStats, 30000);
    return () => clearInterval(interval);
  }, []);
  
  return (
    <div className="grid grid-cols-2 lg:grid-cols-4 gap-5 col-span-full">
      {stats.map((stat, idx) => (
        <div 
          key={idx}
          onClick={() => stat.page && setCurrentPage && setCurrentPage(stat.page)}
          className="bg-[#1b1c20] rounded-2xl p-6 hover:bg-[#252628] transition-all duration-300 cursor-pointer group border border-transparent hover:border-[#35383d]"
        >
          <div className="flex items-start justify-between mb-4">
            <div className={`w-12 h-12 rounded-xl ${stat.bgColor} flex items-center justify-center group-hover:scale-110 transition-transform duration-300`}>
              <i className={`${stat.icon} ${stat.textColor} text-xl`}></i>
            </div>
            <div className="text-gray-500 group-hover:text-gray-400 transition-colors">
              <i className="fas fa-arrow-right text-sm"></i>
            </div>
          </div>
          <div className={`text-3xl font-bold text-white mb-1 ${stat.loading ? 'animate-pulse' : ''}`}>
            {stat.value}
          </div>
          <div className="text-gray-400 text-sm">{stat.title}</div>
        </div>
      ))}
    </div>
  );
}

function QuickActionsWidget({ setCurrentPage }) {
  const actions = [
    { title: 'Agregar Inquilino', icon: 'fas fa-user-plus', page: 'add-tenant' },
    { title: 'Ver Inquilinos',    icon: 'fas fa-users',     page: 'inquilinos' },
    { title: 'Departamentos',     icon: 'fas fa-building',  page: 'departamentos' },
    { title: 'Ver Analítica',     icon: 'fas fa-chart-line', page: 'analitica' },
    { title: 'Mantenimiento',     icon: 'fas fa-wrench',    page: 'mantenimiento' },
    { title: 'Configuración',     icon: 'fas fa-cog',       page: 'configuracion' }
  ];
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center mb-5">
        <div className="w-10 h-10 rounded-xl bg-[#fae0d1]/10 flex items-center justify-center mr-3">
          <i className="fas fa-bolt text-[#fae0d1]"></i>
        </div>
        <h3 className="text-lg font-semibold text-white">Acciones Rápidas</h3>
      </div>
      <div className="grid grid-cols-3 gap-3">
        {actions.map((action, idx) => (
          <button
            key={idx}
            onClick={() => setCurrentPage && setCurrentPage(action.page)}
            className="bg-[#252628] hover:bg-[#2f3136] border border-[#35383d]/60 hover:border-[#fae0d1]/30 text-gray-300 hover:text-[#fae0d1] rounded-xl p-3 flex flex-col items-center justify-center transition-all duration-300 hover:scale-[1.03]"
          >
            <i className={`${action.icon} text-lg mb-1.5 text-[#fae0d1]/70`}></i>
            <span className="text-xs font-medium text-center">{action.title}</span>
          </button>
        ))}
      </div>
    </div>
  );
}

function RecentActivityWidget() {
  const [activities, setActivities] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  
  React.useEffect(() => {
    const fetchActivity = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) {
          setActivities([{ type: 'info', text: 'Configura tu organización para ver actividad', time: '', icon: 'fas fa-info-circle', color: 'text-blue-400' }]);
          setLoading(false);
          return;
        }
        
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
          }
        }, { cacheTime: 5 * 60 * 1000 });
        
        if (response.ok) {
          const result = await response.json();
          const tenants = result.data || [];
          
          // Crear actividad basada en los inquilinos
          const recentActivities = [];
          
          // Ordenar por fecha de creación (más reciente primero)
          const sortedTenants = tenants
            .filter(t => t.createdAt)
            .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
            .slice(0, 5);
          
          sortedTenants.forEach(tenant => {
            const date = new Date(tenant.createdAt);
            const timeAgo = getTimeAgo(date);
            
            recentActivities.push({
              type: 'tenant',
              text: `Nuevo inquilino: ${tenant.name}`,
              time: timeAgo,
              icon: 'fas fa-user-plus',
              color: 'text-green-400'
            });
          });
          
          // Agregar inquilinos con pago pendiente
          const overdueTenants = tenants.filter(t => t.paymentStatus === 'overdue').slice(0, 3);
          overdueTenants.forEach(tenant => {
            recentActivities.push({
              type: 'warning',
              text: `Pago pendiente: ${tenant.name}`,
              time: tenant.apartment,
              icon: 'fas fa-exclamation-triangle',
              color: 'text-orange-400'
            });
          });
          
          if (recentActivities.length === 0) {
            recentActivities.push({
              type: 'info',
              text: 'Sin actividad reciente',
              time: 'Agrega inquilinos para ver actividad',
              icon: 'fas fa-info-circle',
              color: 'text-gray-400'
            });
          }
          
          setActivities(recentActivities);
        }
      } catch (error) {
        console.error('Error fetching activity:', error);
        setActivities([{ type: 'error', text: 'Error al cargar actividad', time: '', icon: 'fas fa-exclamation-circle', color: 'text-red-400' }]);
      }
      setLoading(false);
    };
    
    fetchActivity();
  }, []);
  
  // Función para calcular tiempo transcurrido
  const getTimeAgo = (date) => {
    const now = new Date();
    const diffMs = now - date;
    const diffMins = Math.floor(diffMs / 60000);
    const diffHours = Math.floor(diffMs / 3600000);
    const diffDays = Math.floor(diffMs / 86400000);
    
    if (diffMins < 1) return 'Ahora mismo';
    if (diffMins < 60) return `Hace ${diffMins} min`;
    if (diffHours < 24) return `Hace ${diffHours}h`;
    if (diffDays < 7) return `Hace ${diffDays}d`;
    return date.toLocaleDateString('es-ES');
  };
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-green-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-history text-green-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Actividad Reciente</h3>
        </div>
        <button 
          onClick={() => window.setCurrentPage && window.setCurrentPage('inquilinos')}
          className="text-[#fae0d1] text-xs hover:underline flex items-center gap-1 transition-colors hover:text-white"
        >
          Ver todo <i className="fas fa-arrow-right text-[10px]"></i>
        </button>
      </div>
      <div className="space-y-4 max-h-[280px] overflow-y-auto pr-2">
        {loading ? (
          <div className="py-2 space-y-4">
            <SkeletonLoader type="table-row" />
            <SkeletonLoader type="table-row" />
            <SkeletonLoader type="table-row" />
          </div>
        ) : (
          activities.map((activity, idx) => (
            <div key={idx} className="flex items-start space-x-3 p-3 rounded-xl hover:bg-[#252628] transition-colors">
              <div className={`w-8 h-8 rounded-full bg-[#252628] flex items-center justify-center flex-shrink-0`}>
                <i className={`${activity.icon} ${activity.color} text-sm`}></i>
              </div>
              <div className="flex-1 min-w-0">
                <p className="text-white text-sm">{activity.text}</p>
                {activity.time && <p className="text-gray-500 text-xs mt-1">{activity.time}</p>}
              </div>
            </div>
          ))
        )}
      </div>
    </div>
  );
}

function PaymentProgressWidget() {
  const [progress, setProgress] = React.useState(0);
  const [paid, setPaid] = React.useState(0);
  const [pending, setPending] = React.useState(0);
  const [loading, setLoading] = React.useState(true);
  
  const radius = 70;
  const circumference = 2 * Math.PI * radius;
  const strokeDashoffset = circumference - (progress / 100) * circumference;
  
  // Determinar color según el progreso
  const getProgressColor = () => {
    if (progress >= 80) return { start: '#22c55e', end: '#16a34a' }; // Verde
    if (progress >= 50) return { start: '#d4a574', end: '#c4956a' }; // Oro suave
    return { start: '#ef4444', end: '#dc2626' }; // Rojo
  };
  
  const progressColor = getProgressColor();
  
  React.useEffect(() => {
    const fetchPaymentProgress = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) {
          setLoading(false);
          return;
        }
        
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
          }
        }, { cacheTime: 5 * 60 * 1000 });
        
        if (response.ok) {
          const result = await response.json();
          const tenants = result.data || [];
          const activeTenants = tenants.filter(t => t.status !== 'archived');
          
          const paidCount = activeTenants.filter(t => t.paymentStatus === 'current' || t.paymentStatus === 'advanced').length;
          const pendingCount = activeTenants.filter(t => t.paymentStatus === 'overdue').length;
          const total = activeTenants.length;
          
          setPaid(paidCount);
          setPending(pendingCount);
          setProgress(total > 0 ? Math.round((paidCount / total) * 100) : 0);
        }
      } catch (error) {
        console.error('Error fetching payment progress:', error);
      }
      setLoading(false);
    };
    
    fetchPaymentProgress();
  }, []);
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-purple-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-chart-pie text-purple-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Progreso de Pagos</h3>
        </div>
        <button 
          onClick={() => window.setCurrentPage && window.setCurrentPage('analitica')}
          className="text-[#fae0d1] text-xs hover:underline flex items-center gap-1 transition-colors hover:text-white"
        >
          Ver detalles <i className="fas fa-arrow-right text-[10px]"></i>
        </button>
      </div>
      
      <div className="flex items-center justify-center">
        <div className="relative w-48 h-48">
          {loading ? (
            <div className="w-full h-full flex items-center justify-center">
              <SkeletonLoader type="stat" className="items-center" />
            </div>
          ) : (
            <>
              <svg className="w-full h-full transform -rotate-90" viewBox="0 0 180 180">
                <circle
                  cx="90"
                  cy="90"
                  r={radius}
                  stroke="#35383d"
                  strokeWidth="12"
                  fill="none"
                />
                <circle
                  cx="90"
                  cy="90"
                  r={radius}
                  stroke={`url(#progressGradient-${progress})`}
                  strokeWidth="12"
                  fill="none"
                  strokeLinecap="round"
                  strokeDasharray={circumference}
                  strokeDashoffset={strokeDashoffset}
                  className="transition-all duration-1000 ease-out"
                />
                <defs>
                  <linearGradient id={`progressGradient-${progress}`} x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stopColor={progressColor.start} />
                    <stop offset="100%" stopColor={progressColor.end} />
                  </linearGradient>
                </defs>
              </svg>
              <div className="absolute inset-0 flex flex-col items-center justify-center">
                <span className="text-4xl font-bold text-white">{progress}%</span>
                <span className="text-gray-400 text-sm mt-1">Completado</span>
              </div>
            </>
          )}
        </div>
      </div>
      
      <div className="mt-6 grid grid-cols-2 gap-4">
        <div className="bg-[#252628] rounded-xl p-3 text-center">
          <div className="text-2xl font-bold text-green-400">{paid}</div>
          <div className="text-gray-400 text-xs">Pagados</div>
        </div>
        <div className="bg-[#252628] rounded-xl p-3 text-center">
          <div className="text-2xl font-bold text-orange-400">{pending}</div>
          <div className="text-gray-400 text-xs">Pendientes</div>
        </div>
      </div>
    </div>
  );
}

function UpcomingPaymentsWidget() {
  const [upcomingPayments, setUpcomingPayments] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  
  React.useEffect(() => {
    const fetchUpcoming = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) {
          setLoading(false);
          return;
        }
        
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
          }
        }, { cacheTime: 5 * 60 * 1000 });
        
        if (response.ok) {
          const result = await response.json();
          const tenants = result.data || [];
          
          // Filtrar inquilinos con contratos próximos a vencer (próximos 30 días)
          const today = new Date();
          const thirtyDaysFromNow = new Date(today.getTime() + 30 * 24 * 60 * 60 * 1000);
          
          const upcoming = tenants
            .filter(t => {
              const endDate = t.endDate || t.contractEnd;
              if (!endDate || t.status === 'archived') return false;
              const contractEnd = new Date(endDate);
              return contractEnd >= today && contractEnd <= thirtyDaysFromNow;
            })
            .map(t => {
              const endDate = new Date(t.endDate || t.contractEnd);
              const daysLeft = Math.ceil((endDate - today) / (1000 * 60 * 60 * 24));
              return {
                tenant: t.name,
                apartment: t.apartment,
                amount: `$${(t.rentAmount || 0).toLocaleString('es-MX')}`,
                dueDate: `${daysLeft} días`,
                daysLeft
              };
            })
            .sort((a, b) => a.daysLeft - b.daysLeft)
            .slice(0, 5);
          
          setUpcomingPayments(upcoming);
        }
      } catch (error) {
        console.error('Error fetching upcoming:', error);
      }
      setLoading(false);
    };
    
    fetchUpcoming();
  }, []);
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-orange-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-calendar-alt text-orange-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Próximos Vencimientos</h3>
        </div>
        <div className="flex items-center gap-3">
          <span className="bg-orange-500/20 text-orange-400 px-3 py-1 rounded-full text-xs font-medium">
            {upcomingPayments.length} próximos
          </span>
          <button 
            onClick={() => window.setCurrentPage && window.setCurrentPage('inquilinos')}
            className="text-[#fae0d1] text-xs hover:underline flex items-center gap-1 transition-colors hover:text-white"
          >
            Ver todo <i className="fas fa-arrow-right text-[10px]"></i>
          </button>
        </div>
      </div>
      
      {loading ? (
        <div className="py-2 space-y-3">
          <SkeletonLoader type="table-row" />
          <SkeletonLoader type="table-row" />
        </div>
      ) : upcomingPayments.length === 0 ? (
        <div className="flex flex-col items-center justify-center py-8 text-center">
          <div className="w-16 h-16 rounded-full bg-[#252628] flex items-center justify-center mb-4">
            <i className="fas fa-calendar-check text-gray-500 text-2xl"></i>
          </div>
          <p className="text-gray-400 text-sm">No hay vencimientos próximos</p>
          <p className="text-gray-500 text-xs mt-1">Los contratos próximos a vencer aparecerán aquí</p>
        </div>
      ) : (
        <div className="space-y-3">
          {upcomingPayments.map((payment, idx) => (
            <div key={idx} className="flex items-center justify-between p-3 bg-[#252628] rounded-xl hover:bg-[#35383d] transition-colors">
              <div className="flex items-center">
                <div className="w-10 h-10 rounded-full bg-[#35383d] flex items-center justify-center mr-3">
                  <i className="fas fa-user text-gray-400"></i>
                </div>
                <div>
                  <div className="text-white font-medium">{payment.tenant}</div>
                  <div className="text-gray-400 text-xs">{payment.apartment}</div>
                </div>
              </div>
              <div className="text-right">
                <div className="text-[#fae0d1] font-semibold">{payment.amount}</div>
                <div className="text-gray-500 text-xs">{payment.dueDate}</div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function MonthlyOverviewWidget() {
  const months = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'];
  const currentMonth = new Date().getMonth();
  const currentYear = new Date().getFullYear();
  const [monthlyData, setMonthlyData] = React.useState(months.map(() => 0));
  const [loading, setLoading] = React.useState(true);
  const [showGrowth, setShowGrowth] = React.useState(true);
  
  React.useEffect(() => {
    const fetchMonthlyData = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) {
          setLoading(false);
          return;
        }
        
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
          }
        }, { cacheTime: 10 * 60 * 1000 }); // Caché de 10 minutos para datos históricos
        
        if (response.ok) {
          const result = await response.json();
          const tenants = result.data || [];
          
          // Calcular ingresos potenciales por mes basado en inquilinos activos
          const activeTenants = tenants.filter(t => t.status !== 'archived');
          const monthlyIncome = activeTenants.reduce((sum, t) => sum + (parseFloat(t.rentAmount) || 0), 0);
          
          // Simular datos mensuales (en producción esto vendría de pagos reales)
          const data = months.map((_, idx) => {
            if (idx <= currentMonth) {
              // Meses pasados: variación aleatoria del ingreso base
              return Math.round(monthlyIncome * (0.7 + Math.random() * 0.3));
            }
            return 0; // Meses futuros
          });
          
          setMonthlyData(data);
        }
      } catch (error) {
        console.error('Error fetching monthly data:', error);
      }
      setLoading(false);
    };
    
    fetchMonthlyData();
  }, []);
  
  const maxValue = Math.max(...monthlyData, 1);
  
  // Calcular datos de crecimiento (porcentaje de cambio respecto al mes anterior)
  const growthData = monthlyData.map((value, idx) => {
    if (idx === 0 || monthlyData[idx - 1] === 0) return 0;
    return ((value - monthlyData[idx - 1]) / monthlyData[idx - 1]) * 100;
  });
  
  // Calcular totales para mostrar
  const totalYear = monthlyData.slice(0, currentMonth + 1).reduce((sum, v) => sum + v, 0);
  const avgGrowth = growthData.slice(1, currentMonth + 1).filter(g => g !== 0).length > 0
    ? growthData.slice(1, currentMonth + 1).reduce((sum, g) => sum + g, 0) / growthData.slice(1, currentMonth + 1).filter(g => g !== 0).length
    : 0;
  
  // Ref para el canvas de Chart.js
  const chartRef = React.useRef(null);
  const chartInstance = React.useRef(null);
  
  // Inicializar/actualizar Chart.js
  React.useEffect(() => {
    if (loading || !chartRef.current) return;
    
    // Cargar Chart.js si no está disponible
    if (!window.Chart) {
      const script = document.createElement('script');
      script.src = 'https://cdn.jsdelivr.net/npm/chart.js';
      script.onload = () => createChart();
      document.head.appendChild(script);
    } else {
      createChart();
    }
    
    function createChart() {
      // Destruir gráfico anterior si existe
      if (chartInstance.current) {
        chartInstance.current.destroy();
      }
      
      const ctx = chartRef.current.getContext('2d');
      
      // Colores para las barras
      const barColors = months.map((_, idx) => {
        if (idx === currentMonth) return '#fae0d1';
        if (idx <= currentMonth) return '#35383d';
        return '#252628';
      });
      
      const barHoverColors = months.map((_, idx) => {
        if (idx === currentMonth) return '#c4877e';
        if (idx <= currentMonth) return '#45484d';
        return '#35383d';
      });
      
      // Datos para la línea de tendencia
      const trendData = monthlyData.map((val, idx) => idx <= currentMonth ? val : null);
      
      chartInstance.current = new window.Chart(ctx, {
        type: 'bar',
        data: {
          labels: months,
          datasets: [
            {
              label: 'Ingresos',
              data: monthlyData,
              backgroundColor: barColors,
              hoverBackgroundColor: barHoverColors,
              borderRadius: 6,
              borderSkipped: false,
              barThickness: 'flex',
              maxBarThickness: 24,
              order: 2
            },
            ...(showGrowth ? [{
              label: 'Tendencia',
              data: trendData,
              type: 'line',
              borderColor: '#10b981',
              backgroundColor: 'rgba(16, 185, 129, 0.1)',
              fill: true,
              tension: 0.4,
              pointRadius: 4,
              pointBackgroundColor: '#10b981',
              pointBorderColor: '#1b1c20',
              pointBorderWidth: 2,
              pointHoverRadius: 6,
              order: 1
            }] : [])
          ]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          interaction: {
            intersect: false,
            mode: 'index'
          },
          plugins: {
            legend: {
              display: false
            },
            tooltip: {
              backgroundColor: '#252628',
              titleColor: '#fff',
              bodyColor: '#fff',
              borderColor: '#444',
              borderWidth: 1,
              padding: 12,
              displayColors: false,
              callbacks: {
                title: function(context) {
                  return months[context[0].dataIndex];
                },
                label: function(context) {
                  const value = context.parsed.y;
                  const idx = context.dataIndex;
                  const growth = idx > 0 ? growthData[idx] : 0;
                  
                  let label = `$${value.toLocaleString('es-MX')}`;
                  if (idx > 0 && growth !== 0 && context.dataset.label === 'Ingresos') {
                    const arrow = growth > 0 ? '↑' : '↓';
                    label += ` (${arrow} ${Math.abs(growth).toFixed(1)}%)`;
                  }
                  return label;
                }
              }
            }
          },
          scales: {
            x: {
              grid: {
                display: false
              },
              ticks: {
                color: function(context) {
                  return context.index === currentMonth ? '#fae0d1' : '#666';
                },
                font: function(context) {
                  return {
                    weight: context.index === currentMonth ? 'bold' : 'normal',
                    size: 11
                  };
                }
              }
            },
            y: {
              display: false,
              beginAtZero: true
            }
          }
        }
      });
    }
    
    return () => {
      if (chartInstance.current) {
        chartInstance.current.destroy();
      }
    };
  }, [loading, monthlyData, showGrowth, currentMonth]);
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 col-span-full lg:col-span-2 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-blue-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-chart-bar text-blue-400"></i>
          </div>
          <div>
            <h3 className="text-lg font-semibold text-white">Resumen Anual</h3>
            <p className="text-gray-400 text-xs">Ingresos por mes - {currentYear}</p>
          </div>
        </div>
        <div className="flex items-center space-x-3">
          <button 
            onClick={() => window.setCurrentPage && window.setCurrentPage('analitica')}
            className="text-[#fae0d1] text-xs hover:underline flex items-center gap-1 transition-colors hover:text-white"
          >
            Ver detalles <i className="fas fa-arrow-right text-[10px]"></i>
          </button>
          <button 
            onClick={() => setShowGrowth(!showGrowth)}
            className={`text-xs px-2 py-1 rounded-full transition-colors ${showGrowth ? 'bg-emerald-500/20 text-emerald-400' : 'bg-gray-700 text-gray-400'}`}
          >
            <i className="fas fa-chart-line mr-1"></i>
            Tendencia
          </button>
          <span className="flex items-center text-xs text-gray-400">
            <span className="w-3 h-3 rounded-full bg-[#fae0d1] mr-1"></span>
            Ingresos
          </span>
        </div>
      </div>
      
      {loading ? (
        <div className="flex items-end justify-center h-48 w-full">
          <SkeletonLoader type="chart" className="w-full" />
        </div>
      ) : (
        <>
          {/* Gráfico con Chart.js */}
          <div className="h-48">
            <canvas ref={chartRef}></canvas>
          </div>
          
          {/* Resumen de crecimiento */}
          <div className="flex items-center justify-between mt-4 pt-4 border-t border-gray-800">
            <div className="flex items-center space-x-4">
              <div>
                <p className="text-xs text-gray-500">Total acumulado</p>
                <p className="text-lg font-bold text-white">${totalYear.toLocaleString('es-MX')}</p>
              </div>
            </div>
            <div className="flex items-center space-x-2">
              <div className={`flex items-center px-3 py-1.5 rounded-full ${avgGrowth >= 0 ? 'bg-emerald-500/10' : 'bg-red-500/10'}`}>
                <i className={`fas fa-${avgGrowth >= 0 ? 'arrow-up' : 'arrow-down'} text-xs ${avgGrowth >= 0 ? 'text-emerald-400' : 'text-red-400'} mr-1.5`}></i>
                <span className={`text-sm font-semibold ${avgGrowth >= 0 ? 'text-emerald-400' : 'text-red-400'}`}>
                  {Math.abs(avgGrowth).toFixed(1)}%
                </span>
              </div>
              <span className="text-xs text-gray-500">promedio</span>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

function SystemStatusWidget() {
  // Estados: 'checking', 'online', 'partial', 'offline', 'api-down'
  const [systemStatus, setSystemStatus] = React.useState('checking');
  const [cacheStats, setCacheStats] = React.useState(null);
  
  React.useEffect(() => {
    const checkSystemStatus = async () => {
      const token = getJWTFromStorage();
      const hasOrg = window.currentOrganizationId || localStorage.getItem('organizationId');
      
      let authOk = !!token;
      let orgOk = !!hasOrg;
      
      // Verificar conexión a internet
      const isOnline = await CacheManager.checkRealConnection();
      
      // Verificar si el API está funcionando
      const apiWorking = await CacheManager.checkAPIStatus();
      
      // Obtener estadísticas de caché
      const stats = CacheManager.getStats();
      setCacheStats(stats);
      
      // Determinar estado general
      if (!isOnline) {
        // Sin conexión a internet
        setSystemStatus('offline');
      } else if (!apiWorking) {
        // Internet funciona pero el API no responde
        setSystemStatus('api-down');
      } else if (authOk && orgOk) {
        // Todo funcionando
        setSystemStatus('online');
      } else {
        // API funciona pero hay problemas de sesión
        setSystemStatus('partial');
      }
    };
    
    checkSystemStatus();
    // Verificar cada 30 segundos para detectar cambios más rápido
    const interval = setInterval(checkSystemStatus, 30000);
    return () => clearInterval(interval);
  }, []);
  
  const getStatusContent = () => {
    switch (systemStatus) {
      case 'checking':
        return {
          emoji: '🔄',
          title: 'Verificando...',
          message: 'Estamos comprobando el estado del sistema',
          textColor: 'text-gray-400'
        };
      case 'online':
        return {
          emoji: '😊',
          title: '¡Todo funcionando de maravilla!',
          message: 'Todos nuestros sistemas están operativos',
          textColor: 'text-green-400'
        };
      case 'partial':
        return {
          emoji: '😟',
          title: 'Problemas de sesión',
          message: 'El servidor funciona pero hay problemas con tu sesión',
          textColor: 'text-orange-400'
        };
      case 'api-down':
        return {
          emoji: 'sad',
          title: 'Parece que tenemos problemas graves de nuestra parte',
          message: 'Pero no te preocupes, guardaremos localmente lo que hagas hasta que los arreglemos. ¡Lo sentimos!',
          textColor: 'text-red-400'
        };
      case 'offline':
        return {
          emoji: '📴',
          title: 'Sin conexión a internet',
          message: 'Usando datos guardados en caché. Los cambios se sincronizarán cuando vuelvas a conectarte.',
          textColor: 'text-orange-400'
        };
      default:
        return {
          emoji: '🔄',
          title: 'Verificando...',
          message: '',
          textColor: 'text-gray-400'
        };
    }
  };
  
  const status = getStatusContent();
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center mb-5">
        <div className="w-10 h-10 rounded-xl bg-[#252628] flex items-center justify-center mr-3">
          <i className="fas fa-heartbeat text-gray-400"></i>
        </div>
        <h3 className="text-lg font-semibold text-white">Estado del Sistema</h3>
      </div>
      
      <div className="text-center py-4">
        {systemStatus === 'checking' ? (
          <div className="flex flex-col items-center justify-center py-4 w-full">
            <SkeletonLoader type="stat" className="items-center w-full" />
          </div>
        ) : (
          <>
            {status.emoji === 'sad' ? (
              <div className="text-6xl mb-4">😓</div>
            ) : (
              <div className="text-6xl mb-4">{status.emoji}</div>
            )}
            <h4 className={`text-lg font-semibold ${status.textColor} mb-2`}>{status.title}</h4>
            <p className="text-gray-400 text-sm">{status.message}</p>
          </>
        )}
      </div>
    </div>
  );
}

function PaymentSummaryWidget() {
  const [totalRevenue, setTotalRevenue] = React.useState(0);
  const [paymentsCount, setPaymentsCount] = React.useState(0);
  const [pendingAmount, setPendingAmount] = React.useState(0);
  const [pendingCount, setPendingCount] = React.useState(0);
  const [recentTenants, setRecentTenants] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  
  React.useEffect(() => {
    const fetchPaymentSummary = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) {
          setLoading(false);
          return;
        }
        
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
          }
        }, { cacheTime: 5 * 60 * 1000 });
        
        if (response.ok) {
          const result = await response.json();
          const tenants = result.data || [];
          const activeTenants = tenants.filter(t => t.status !== 'archived');
          
          // Calcular totales
          const paidTenants = activeTenants.filter(t => t.paymentStatus === 'current' || t.paymentStatus === 'advanced');
          const overdueTenants = activeTenants.filter(t => t.paymentStatus === 'overdue');
          
          const revenue = paidTenants.reduce((sum, t) => sum + (parseFloat(t.rentAmount) || 0), 0);
          const pending = overdueTenants.reduce((sum, t) => sum + (parseFloat(t.rentAmount) || 0), 0);
          
          setTotalRevenue(revenue);
          setPaymentsCount(paidTenants.length);
          setPendingAmount(pending);
          setPendingCount(overdueTenants.length);
          
          // Obtener pagos reales del historial de todos los inquilinos
          const allPayments = [];
          activeTenants.forEach(t => {
            if (t.paymentHistory && t.paymentHistory.length > 0) {
              t.paymentHistory.forEach(p => {
                allPayments.push({
                  tenant: t.name,
                  apartment: t.apartment,
                  amount: parseFloat(p.amount) || 0,
                  date: new Date(p.date || p.registeredAt).toLocaleDateString('es-ES'),
                  rawDate: new Date(p.date || p.registeredAt),
                  method: p.method || 'No especificado',
                  isPaid: true
                });
              });
            }
          });
          
          // También agregar inquilinos overdue como pagos pendientes si no tienen historial reciente
          overdueTenants.forEach(t => {
            if (!t.paymentHistory || t.paymentHistory.length === 0) {
              allPayments.push({
                tenant: t.name,
                apartment: t.apartment,
                amount: parseFloat(t.rentAmount) || 0,
                date: 'Pendiente',
                rawDate: new Date(0),
                method: '',
                isPaid: false
              });
            }
          });
          
          // Ordenar por fecha más reciente y tomar los últimos 6
          const recent = allPayments
            .sort((a, b) => b.rawDate - a.rawDate)
            .slice(0, 6);
          
          setRecentTenants(recent);
        }
      } catch (error) {
        console.error('Error fetching payment summary:', error);
      }
      setLoading(false);
    };
    
    fetchPaymentSummary();
  }, []);
  
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 col-span-full hover-lift">
      <div className="flex items-center justify-between mb-6">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-[#fae0d1]/10 flex items-center justify-center mr-3">
            <i className="fas fa-wallet text-[#fae0d1]"></i>
          </div>
          <div>
            <h3 className="text-lg font-semibold text-white">Resumen de Ingresos</h3>
            <p className="text-gray-400 text-xs">Balance general del mes</p>
          </div>
        </div>
        <div className="flex items-center gap-3">
          <button 
            onClick={() => window.setCurrentPage && window.setCurrentPage('analitica')}
            className="text-[#fae0d1] text-xs hover:underline flex items-center gap-1 transition-colors hover:text-white"
          >
            Ver detalles <i className="fas fa-arrow-right text-[10px]"></i>
          </button>
          <button className="bg-[#35383d] hover:bg-[#45484d] text-white px-4 py-2 rounded-xl text-sm transition-colors">
            <i className="fas fa-download mr-2"></i>
            Exportar
          </button>
        </div>
      </div>
      
      {loading ? (
        <div className="py-4 space-y-4">
          <SkeletonLoader type="table-row" />
          <SkeletonLoader type="table-row" />
          <SkeletonLoader type="table-row" />
        </div>
      ) : (
        <>
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
            <div className="bg-gradient-to-br from-green-500/20 to-green-600/10 rounded-xl p-5 border border-green-500/20">
              <div className="flex items-center justify-between mb-3">
                <span className="text-gray-300 text-sm">Total Recaudado</span>
                <div className="w-10 h-10 rounded-full bg-green-500/20 flex items-center justify-center">
                  <i className="fas fa-arrow-up text-green-400"></i>
                </div>
              </div>
              <div className="text-3xl font-bold text-white">${totalRevenue.toLocaleString('es-MX')}</div>
              <div className="text-green-400 text-xs mt-2 flex items-center">
                <i className="fas fa-check-circle mr-1"></i>
                {paymentsCount} pagos al día
              </div>
            </div>
            
            <div className="bg-gradient-to-br from-blue-500/20 to-blue-600/10 rounded-xl p-5 border border-blue-500/20">
              <div className="flex items-center justify-between mb-3">
                <span className="text-gray-300 text-sm">Pagos Recibidos</span>
                <div className="w-10 h-10 rounded-full bg-blue-500/20 flex items-center justify-center">
                  <i className="fas fa-receipt text-blue-400"></i>
                </div>
              </div>
              <div className="text-3xl font-bold text-white">{paymentsCount}</div>
              <div className="text-blue-400 text-xs mt-2 flex items-center">
                <i className="fas fa-users mr-1"></i>
                Inquilinos al corriente
              </div>
            </div>
            
            <div className="bg-gradient-to-br from-orange-500/20 to-orange-600/10 rounded-xl p-5 border border-orange-500/20">
              <div className="flex items-center justify-between mb-3">
                <span className="text-gray-300 text-sm">Pendiente por Cobrar</span>
                <div className="w-10 h-10 rounded-full bg-orange-500/20 flex items-center justify-center">
                  <i className="fas fa-hourglass-half text-orange-400"></i>
                </div>
              </div>
              <div className="text-3xl font-bold text-white">${pendingAmount.toLocaleString('es-MX')}</div>
              <div className="text-orange-400 text-xs mt-2 flex items-center">
                <i className="fas fa-clock mr-1"></i>
                {pendingCount} pagos pendientes
              </div>
            </div>
          </div>
          
          {recentTenants.length > 0 ? (
            <div>
              <h4 className="text-white font-medium mb-4">Pagos Recientes</h4>
              <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
                {recentTenants.map((payment, idx) => (
                  <div key={idx} className={`flex items-center justify-between rounded-xl p-4 transition-colors ${payment.isPaid ? 'bg-[#252628] hover:bg-[#35383d]' : 'bg-red-900/20 hover:bg-red-900/30 border border-red-500/20'}`}>
                    <div className="flex items-center min-w-0 flex-1">
                      <div className={`w-10 h-10 rounded-full flex items-center justify-center mr-3 flex-shrink-0 ${payment.isPaid ? 'bg-[#fae0d1]' : 'bg-red-500/20'}`}>
                        <i className={`fas ${payment.isPaid ? 'fa-check text-[#1b1c20]' : 'fa-exclamation text-red-400'}`}></i>
                      </div>
                      <div className="min-w-0 flex-1">
                        <div className="text-white font-medium truncate">{payment.tenant}</div>
                        <div className="text-gray-400 text-xs truncate">{payment.apartment}</div>
                      </div>
                    </div>
                    <div className="text-right flex-shrink-0 ml-3">
                      <div className={`font-semibold ${payment.isPaid ? 'text-[#fae0d1]' : 'text-red-400'}`}>${payment.amount.toLocaleString('es-MX')}</div>
                      <div className={`text-xs ${payment.isPaid ? 'text-gray-500' : 'text-red-400/70'}`}>{payment.date}</div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          ) : (
            <div className="flex flex-col items-center justify-center py-8 bg-[#252628] rounded-xl">
              <div className="w-16 h-16 rounded-full bg-[#35383d] flex items-center justify-center mb-4">
                <i className="fas fa-receipt text-gray-500 text-2xl"></i>
              </div>
              <p className="text-gray-400 text-sm">No hay pagos registrados este mes</p>
              <p className="text-gray-500 text-xs mt-1">Los pagos recientes aparecerán aquí</p>
            </div>
          )}
        </>
      )}
    </div>
  );
}

// Placeholder page for sections under development
function PlaceholderPage({ title, icon, color, description, setCurrentPage }) {
  const colorMap = {
    blue:   { bg: 'bg-blue-500/10',   text: 'text-blue-400',   border: 'border-blue-500/20',   ring: 'ring-blue-500/30' },
    yellow: { bg: 'bg-yellow-500/10',  text: 'text-yellow-400', border: 'border-yellow-500/20', ring: 'ring-yellow-500/30' },
    purple: { bg: 'bg-purple-500/10',  text: 'text-purple-400', border: 'border-purple-500/20', ring: 'ring-purple-500/30' },
    green:  { bg: 'bg-green-500/10',   text: 'text-green-400',  border: 'border-green-500/20',  ring: 'ring-green-500/30' },
    gray:   { bg: 'bg-gray-500/10',    text: 'text-gray-400',   border: 'border-gray-500/20',   ring: 'ring-gray-500/30' },
  };
  const c = colorMap[color] || colorMap.gray;

  return (
    <div className="flex flex-col items-center justify-center min-h-[60vh] content-fade-in">
      <div className={`w-24 h-24 rounded-3xl ${c.bg} ${c.border} border flex items-center justify-center mb-6 ring-4 ${c.ring}`}>
        <i className={`${icon} ${c.text} text-4xl`}></i>
      </div>
      <h1 className="text-3xl font-bold text-white mb-3">{title}</h1>
      <p className="text-gray-400 text-center max-w-md mb-8">{description}</p>
      <div className="flex items-center gap-3">
        <span className="bg-[#fae0d1]/20 text-[#fae0d1] px-4 py-2 rounded-full text-sm font-medium">
          <i className="fas fa-hammer mr-2"></i>En desarrollo
        </span>
        <button
          onClick={() => setCurrentPage('dashboard')}
          className="bg-[#35383d] hover:bg-[#45484d] text-white px-4 py-2 rounded-xl text-sm transition-colors"
        >
          <i className="fas fa-arrow-left mr-2"></i>Volver al Dashboard
        </button>
      </div>
    </div>
  );
}

// ============================================
// ANALYTICS WIDGET REGISTRY & LAYOUT
// ============================================
const ANALYTICS_WIDGET_REGISTRY = {
  'analytics-income':      { label: 'Ingresos del Mes',    icon: 'fas fa-dollar-sign', defaultSpan: 4 },
  'analytics-occupancy':   { label: 'Ocupación Global',    icon: 'fas fa-building',    defaultSpan: 2 },
  'analytics-pending':     { label: 'Pagos Pendientes',    icon: 'fas fa-exclamation', defaultSpan: 2 },
  'analytics-top-props':   { label: 'Top Propiedades',     icon: 'fas fa-star',        defaultSpan: 2 },
  'analytics-trend':       { label: 'Crecimiento Anual',   icon: 'fas fa-chart-line',  defaultSpan: 4 },
  'analytics-maintenance': { label: 'Tickets Abiertos',    icon: 'fas fa-wrench',      defaultSpan: 2 },
};

const ANALYTICS_DEFAULT_LAYOUT = [
  { id: 'analytics-income', span: 4 },
  { id: 'analytics-occupancy', span: 2 },
  { id: 'analytics-pending', span: 2 },
  { id: 'analytics-top-props', span: 2 },
  { id: 'analytics-trend', span: 4 },
  { id: 'analytics-maintenance', span: 2 },
];

const ANALYTICS_LAYOUT_STORAGE_KEY = 'esperiency_analytics_layout';

function loadAnalyticsLayout() {
  try {
    const saved = localStorage.getItem(ANALYTICS_LAYOUT_STORAGE_KEY);
    if (saved) {
      const parsed = JSON.parse(saved);
      if (Array.isArray(parsed) && parsed.length > 0 && parsed.every(item => item.id && ANALYTICS_WIDGET_REGISTRY[item.id])) {
        return parsed;
      }
    }
  } catch (e) { console.error('Error loading analytics layout:', e); }
  return ANALYTICS_DEFAULT_LAYOUT.map(item => ({ ...item }));
}

function saveAnalyticsLayout(layout) {
  try { localStorage.setItem(ANALYTICS_LAYOUT_STORAGE_KEY, JSON.stringify(layout)); }
  catch (e) { console.error('Error saving analytics layout:', e); }
}

function renderAnalyticsWidget(widgetId, props) {
  switch (widgetId) {
    case 'analytics-income':      return <AnalyticsIncomeWidget {...props} />;
    case 'analytics-occupancy':   return <AnalyticsOccupancyWidget {...props} />;
    case 'analytics-pending':     return <AnalyticsPendingWidget {...props} />;
    case 'analytics-top-props':   return <AnalyticsTopPropsWidget {...props} />;
    case 'analytics-trend':       return <AnalyticsTrendWidget {...props} />;
    case 'analytics-maintenance': return <AnalyticsMaintenanceWidget {...props} />;
    default: return null;
  }
}

// Data Context Provider for Analytics Widgets
const AnalyticsContext = React.createContext();

function AnalyticsWidgets({ setCurrentPage }) {
  const [layout, setLayout] = React.useState(() => loadAnalyticsLayout());
  const [data, setData] = React.useState({
    tenants: [],
    apartments: [],
    loading: true
  });

  React.useEffect(() => {
    const fetchAnalyticsData = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        const token = typeof getJWTFromStorage === 'function' ? getJWTFromStorage() : localStorage.getItem('jwt_token');
        if (!organizationId || !token) return;
        
        const apiUrl = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' 
          ? 'http://localhost:3000' 
          : 'https://api.esperiency.com';

        const headers = { 'Authorization': `Bearer ${token}` };

        const [tRes, pRes] = await Promise.all([
          cachedFetch(`${apiUrl}/api/tenants?organizationId=${organizationId}`, { headers }, { cacheTime: 5*60*1000 }),
          cachedFetch(`${apiUrl}/api/apartments`, { headers }, { cacheTime: 5*60*1000 })
        ]);

        const tData = await tRes.json();
        const pData = await pRes.json();
        
        setData({
          tenants: Array.isArray(tData.data) ? tData.data : [],
          apartments: Array.isArray(pData.data) ? pData.data : [],
          loading: false
        });
      } catch (err) {
        console.error('Error fetching analytics:', err);
        setData(prev => ({ ...prev, loading: false }));
      }
    };
    fetchAnalyticsData();
  }, []);

  return (
    <AnalyticsContext.Provider value={data}>
      <DraggableWidgetGrid 
        setCurrentPage={setCurrentPage}
        layout={layout}
        setLayout={setLayout}
        defaultLayout={ANALYTICS_DEFAULT_LAYOUT}
        widgetRegistry={ANALYTICS_WIDGET_REGISTRY}
        saveLayout={saveAnalyticsLayout}
        renderWidgetContentFn={(id) => renderAnalyticsWidget(id, { setCurrentPage })}
        emptyMessage="Clic o arrastra un widget analítico aquí"
      />
    </AnalyticsContext.Provider>
  );
}

// ============================================
// ANALYTICS SPECIFIC WIDGETS
// ============================================

function AnalyticsIncomeWidget() {
  const { tenants, loading } = React.useContext(AnalyticsContext);
  
  if (loading) return <div className="bg-[#1b1c20] border border-[#252628] rounded-3xl p-6 h-full flex flex-col"><SkeletonLoader type="card" className="h-full border-none p-0" /></div>;

  const totalIncome = tenants.reduce((acc, t) => {
    if (t.paymentHistory && t.paymentHistory.length > 0) {
      return acc + (t.paymentHistory[t.paymentHistory.length - 1].amount || 0);
    }
    return acc;
  }, 0) || 124500; // Mock fallback if no history

  return (
    <div className="bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-3xl p-6 shadow-[var(--shadow)] hover-lift h-full flex flex-col">
      <div className="flex items-start justify-between mb-4">
        <div>
          <h3 className="text-[var(--text-tertiary)] font-medium text-sm uppercase tracking-wider mb-1">Ingresos del Mes</h3>
          <div className="text-4xl font-bold text-[var(--text-primary)]">
            ${totalIncome.toLocaleString('es-MX')}<span className="text-xl text-[var(--text-tertiary)]">.00</span>
          </div>
        </div>
        <div className="w-12 h-12 rounded-2xl bg-green-500/10 text-green-400 flex items-center justify-center text-xl">
          <i className="fas fa-arrow-trend-up"></i>
        </div>
      </div>
      <div className="text-sm text-green-400 font-medium flex items-center gap-1 mb-6">
        <i className="fas fa-caret-up"></i> 12.5% vs mes anterior
      </div>
      <div className="flex-1 min-h-[150px] bg-[var(--bg-tertiary)] rounded-xl flex items-end justify-between p-4 gap-2">
        {[30, 45, 25, 60, 40, 75, 55, 90].map((h, i) => (
          <div key={i} className="w-full bg-[var(--accent)] rounded-t-sm transition-all duration-1000 ease-out animate-fadeInUp" style={{ height: `${h}%`, animationDelay: `${i * 100}ms` }}></div>
        ))}
      </div>
    </div>
  );
}

function AnalyticsOccupancyWidget() {
  const { apartments, loading } = React.useContext(AnalyticsContext);
  
  if (loading) return <div className="bg-[#1b1c20] border border-[#252628] rounded-3xl p-6 h-full flex flex-col items-center justify-center"><SkeletonLoader type="stat" className="items-center" /></div>;

  const total = apartments.length;
  const occupied = apartments.filter(a => a.residents && a.residents.length > 0).length;
  const rate = total > 0 ? Math.round((occupied / total) * 100) : 0;
  
  const radius = 16;
  const circ = 2 * Math.PI * radius;
  const offset = circ - (rate / 100) * circ;

  return (
    <div className="bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-3xl p-6 shadow-[var(--shadow)] hover-lift h-full flex flex-col justify-center items-center">
      <h3 className="text-[var(--text-tertiary)] font-medium text-sm mb-4">Ocupación</h3>
      <div className="relative w-24 h-24 flex items-center justify-center">
        <svg className="w-full h-full transform -rotate-90" viewBox="0 0 36 36">
          <circle cx="18" cy="18" r="16" fill="none" stroke="var(--bg-tertiary)" strokeWidth="3" />
          <circle cx="18" cy="18" r="16" fill="none" stroke="var(--accent)" strokeWidth="3" strokeDasharray={circ} strokeDashoffset={offset} className="transition-all duration-1500 ease-out" />
        </svg>
        <div className="absolute text-xl font-bold text-[var(--text-primary)]">{rate}%</div>
      </div>
    </div>
  );
}

function AnalyticsPendingWidget() {
  const { tenants, loading } = React.useContext(AnalyticsContext);
  
  if (loading) return <div className="bg-[#1b1c20] border border-[#252628] rounded-3xl p-6 h-full flex flex-col justify-center"><SkeletonLoader type="stat" /></div>;

  const pendingCount = tenants.filter(t => t.pendingAmount > 0).length;

  return (
    <div className="bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-3xl p-6 shadow-[var(--shadow)] hover-lift h-full flex flex-col justify-center">
      <div className="w-10 h-10 rounded-full bg-red-500/10 text-red-400 flex items-center justify-center mb-3">
        <i className="fas fa-exclamation-triangle"></i>
      </div>
      <div className="text-3xl font-bold text-[var(--text-primary)]">{pendingCount}</div>
      <h3 className="text-[var(--text-tertiary)] text-sm">Pagos Pendientes</h3>
    </div>
  );
}

function AnalyticsTopPropsWidget() {
  const { apartments, loading } = React.useContext(AnalyticsContext);
  
  if (loading) return <div className="bg-[#1b1c20] border border-[#252628] rounded-3xl p-6 h-full flex flex-col"><SkeletonLoader type="table-row" className="h-full border-none p-0 flex-col" /></div>;

  const topApts = apartments.slice(0, 4);

  return (
    <div className="bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-3xl p-6 shadow-[var(--shadow)] hover-lift h-full flex flex-col">
      <h3 className="text-[var(--text-primary)] font-medium mb-4">Top Propiedades</h3>
      <div className="flex flex-col gap-4 flex-1 overflow-hidden">
        {topApts.length === 0 ? (
           <div className="text-sm text-gray-500">No hay propiedades</div>
        ) : topApts.map((apt, i) => (
          <div key={apt.id || i} className="flex items-center justify-between pb-3 border-b border-[var(--border-primary)] last:border-0 last:pb-0">
            <div className="flex items-center gap-3">
              <div className="w-8 h-8 rounded-lg bg-[var(--bg-tertiary)] flex items-center justify-center text-xs font-bold text-[var(--text-primary)]">{i + 1}</div>
              <div>
                <div className="text-sm text-[var(--text-primary)] font-medium truncate max-w-[120px]">{apt.number || `Unidad ${i+1}`}</div>
                <div className="text-xs text-[var(--text-tertiary)]">{apt.residents?.length ? 'Ocupado' : 'Vacante'}</div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function AnalyticsTrendWidget() {
  const { loading } = React.useContext(AnalyticsContext);
  
  if (loading) return <div className="bg-[#1b1c20] border border-[#252628] rounded-3xl p-6 h-full flex items-center justify-between"><SkeletonLoader type="chart" className="w-full" /></div>;

  return (
    <div className="bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-3xl p-6 shadow-[var(--shadow)] hover-lift h-full flex items-center justify-between">
      <div>
        <h3 className="text-[var(--text-tertiary)] font-medium text-sm mb-1">Crecimiento Anual</h3>
        <div className="text-3xl font-bold text-[var(--text-primary)]">+24.5%</div>
      </div>
      <div className="flex gap-2 h-16 items-end">
        {[20, 30, 45, 60, 50, 70, 85].map((h, i) => (
          <div key={i} className="w-4 bg-[var(--accent)] rounded-t-sm" style={{ height: `${h}%` }}></div>
        ))}
      </div>
    </div>
  );
}

function AnalyticsMaintenanceWidget() {
  const { loading } = React.useContext(AnalyticsContext);
  
  if (loading) return <div className="bg-[#1b1c20] border border-[#252628] rounded-3xl p-6 h-full flex flex-col justify-center"><SkeletonLoader type="stat" /></div>;

  return (
    <div className="bg-[var(--bg-primary)] border border-[var(--border-primary)] rounded-3xl p-6 shadow-[var(--shadow)] hover-lift h-full flex flex-col justify-center">
      <div className="w-10 h-10 rounded-full bg-yellow-500/10 text-yellow-400 flex items-center justify-center mb-3">
        <i className="fas fa-wrench"></i>
      </div>
      <div className="text-3xl font-bold text-[var(--text-primary)]">5</div>
      <h3 className="text-[var(--text-tertiary)] text-sm">Tickets Abiertos</h3>
    </div>
  );
}


// ============================================

function OccupancyWidget() {
  const [occupied, setOccupied] = React.useState(0);
  const [total, setTotal] = React.useState(0);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    const fetchOccupancy = async () => {
      try {
        const token = getJWTFromStorage();
        const response = await cachedFetch('http://localhost:3000/api/apartments', {
          headers: { 'Authorization': `Bearer ${token}` }
        }, { cacheTime: 5 * 60 * 1000 });
        if (response.ok) {
          const result = await response.json();
          const apts = result.data || [];
          setTotal(apts.length);
          setOccupied(apts.filter(a => a.residents && a.residents.length > 0).length);
        }
      } catch (e) { console.error('Occupancy error:', e); }
      setLoading(false);
    };
    fetchOccupancy();
  }, []);

  const rate = total > 0 ? Math.round((occupied / total) * 100) : 0;
  const vacant = total - occupied;
  const radius = 54;
  const circ = 2 * Math.PI * radius;
  const offset = circ - (rate / 100) * circ;
  const rateColor = rate >= 80 ? '#22c55e' : rate >= 50 ? '#f59e0b' : '#ef4444';

  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center mb-5">
        <div className="w-10 h-10 rounded-xl bg-cyan-500/10 flex items-center justify-center mr-3">
          <i className="fas fa-building text-cyan-400"></i>
        </div>
        <h3 className="text-lg font-semibold text-white">Tasa de Ocupación</h3>
      </div>
      {loading ? (
        <div className="py-4">
          <SkeletonLoader type="stat" className="items-center" />
        </div>
      ) : total === 0 ? (
        <div className="flex flex-col items-center py-8">
          <div className="w-14 h-14 rounded-full bg-[#252628] flex items-center justify-center mb-3"><i className="fas fa-building text-gray-500 text-xl"></i></div>
          <p className="text-gray-400 text-sm">Agrega departamentos para ver la ocupación</p>
        </div>
      ) : (
        <div className="flex items-center gap-6">
          <div className="relative w-32 h-32 flex-shrink-0">
            <svg className="w-full h-full -rotate-90" viewBox="0 0 128 128">
              <circle cx="64" cy="64" r={radius} stroke="#252628" strokeWidth="10" fill="none" />
              <circle cx="64" cy="64" r={radius} stroke={rateColor} strokeWidth="10" fill="none" strokeLinecap="round"
                strokeDasharray={circ} strokeDashoffset={offset} className="transition-all duration-1000 ease-out" />
            </svg>
            <div className="absolute inset-0 flex flex-col items-center justify-center">
              <span className="text-2xl font-bold text-white">{rate}%</span>
              <span className="text-gray-500 text-[10px]">ocupado</span>
            </div>
          </div>
          <div className="flex-1 space-y-3">
            <div className="flex items-center justify-between p-3 bg-[#252628] rounded-xl">
              <div className="flex items-center gap-2"><div className="w-2.5 h-2.5 rounded-full bg-green-400"></div><span className="text-gray-300 text-sm">Ocupados</span></div>
              <span className="text-white font-bold">{occupied}</span>
            </div>
            <div className="flex items-center justify-between p-3 bg-[#252628] rounded-xl">
              <div className="flex items-center gap-2"><div className="w-2.5 h-2.5 rounded-full bg-gray-500"></div><span className="text-gray-300 text-sm">Vacantes</span></div>
              <span className="text-white font-bold">{vacant}</span>
            </div>
            <div className="flex items-center justify-between p-3 bg-[#252628] rounded-xl">
              <div className="flex items-center gap-2"><div className="w-2.5 h-2.5 rounded-full bg-cyan-400"></div><span className="text-gray-300 text-sm">Total</span></div>
              <span className="text-white font-bold">{total}</span>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function ContractStatusWidget() {
  const [contracts, setContracts] = React.useState({ active: 0, expiringSoon: 0, expired: 0 });
  const [expiringTenants, setExpiringTenants] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    const fetchContracts = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) { setLoading(false); return; }
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }
        }, { cacheTime: 5 * 60 * 1000 });
        if (response.ok) {
          const result = await response.json();
          const tenants = (result.data || []).filter(t => t.status !== 'archived');
          const today = new Date();
          const thirtyDays = new Date(today.getTime() + 30 * 24 * 60 * 60 * 1000);
          let active = 0, expiringSoon = 0, expired = 0;
          const expiring = [];
          tenants.forEach(t => {
            const end = t.endDate || t.contractEnd;
            if (!end) { active++; return; }
            const endDate = new Date(end);
            if (endDate < today) expired++;
            else if (endDate <= thirtyDays) { expiringSoon++; expiring.push({ name: t.name, days: Math.ceil((endDate - today) / 86400000) }); }
            else active++;
          });
          setContracts({ active, expiringSoon, expired });
          setExpiringTenants(expiring.sort((a, b) => a.days - b.days).slice(0, 4));
        }
      } catch (e) { console.error('Contract status error:', e); }
      setLoading(false);
    };
    fetchContracts();
  }, []);

  const totalContracts = contracts.active + contracts.expiringSoon + contracts.expired;

  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-file-contract text-indigo-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Contratos</h3>
        </div>
        {contracts.expiringSoon > 0 && (
          <span className="bg-yellow-500/20 text-yellow-400 text-xs px-2.5 py-1 rounded-full font-medium">
            {contracts.expiringSoon} por vencer
          </span>
        )}
      </div>
      {loading ? (
        <div className="py-4 flex gap-3">
          <SkeletonLoader type="card" className="w-1/3" />
          <SkeletonLoader type="card" className="w-1/3" />
          <SkeletonLoader type="card" className="w-1/3" />
        </div>
      ) : (
        <>
          <div className="grid grid-cols-3 gap-3 mb-5">
            <div className="bg-green-500/10 rounded-xl p-3 text-center border border-green-500/10">
              <div className="text-2xl font-bold text-green-400">{contracts.active}</div>
              <div className="text-gray-400 text-xs mt-1">Activos</div>
            </div>
            <div className="bg-yellow-500/10 rounded-xl p-3 text-center border border-yellow-500/10">
              <div className="text-2xl font-bold text-yellow-400">{contracts.expiringSoon}</div>
              <div className="text-gray-400 text-xs mt-1">Por vencer</div>
            </div>
            <div className="bg-red-500/10 rounded-xl p-3 text-center border border-red-500/10">
              <div className="text-2xl font-bold text-red-400">{contracts.expired}</div>
              <div className="text-gray-400 text-xs mt-1">Vencidos</div>
            </div>
          </div>
          {totalContracts > 0 && (
            <div className="w-full h-2.5 bg-[#252628] rounded-full overflow-hidden flex mb-4">
              {contracts.active > 0 && <div className="bg-green-500 h-full" style={{ width: `${(contracts.active / totalContracts) * 100}%` }}></div>}
              {contracts.expiringSoon > 0 && <div className="bg-yellow-500 h-full" style={{ width: `${(contracts.expiringSoon / totalContracts) * 100}%` }}></div>}
              {contracts.expired > 0 && <div className="bg-red-500 h-full" style={{ width: `${(contracts.expired / totalContracts) * 100}%` }}></div>}
            </div>
          )}
          {expiringTenants.length > 0 && (
            <div className="space-y-2">
              <div className="text-gray-500 text-xs font-medium uppercase tracking-wider">Próximos a vencer</div>
              {expiringTenants.map((t, i) => (
                <div key={i} className="flex items-center justify-between p-2.5 bg-[#252628] rounded-lg">
                  <span className="text-gray-300 text-sm">{t.name}</span>
                  <span className={`text-xs font-medium px-2 py-0.5 rounded-full ${t.days <= 7 ? 'bg-red-500/20 text-red-400' : 'bg-yellow-500/20 text-yellow-400'}`}>{t.days}d</span>
                </div>
              ))}
            </div>
          )}
        </>
      )}
    </div>
  );
}

function QuickNotesWidget() {
  const NOTES_KEY = 'esperiency_quick_notes';
  const [notes, setNotes] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem(NOTES_KEY)) || []; } catch { return []; }
  });
  const [newNote, setNewNote] = React.useState('');
  const [isAdding, setIsAdding] = React.useState(false);

  const saveNotes = (updated) => {
    setNotes(updated);
    localStorage.setItem(NOTES_KEY, JSON.stringify(updated));
  };

  const addNote = () => {
    if (!newNote.trim()) return;
    saveNotes([{ id: Date.now(), text: newNote.trim(), done: false, createdAt: new Date().toISOString() }, ...notes]);
    setNewNote('');
    setIsAdding(false);
  };

  const toggleDone = (id) => { saveNotes(notes.map(n => n.id === id ? { ...n, done: !n.done } : n)); };
  const removeNote = (id) => { saveNotes(notes.filter(n => n.id !== id)); };

  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-amber-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-sticky-note text-amber-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Notas Rápidas</h3>
        </div>
        <button onClick={() => setIsAdding(!isAdding)} className="w-8 h-8 rounded-lg bg-[#252628] hover:bg-[#35383d] flex items-center justify-center transition-colors group">
          <i className={`fas ${isAdding ? 'fa-times' : 'fa-plus'} text-gray-400 group-hover:text-[#fae0d1] text-xs transition-all duration-200 ${isAdding ? 'rotate-0' : ''}`}></i>
        </button>
      </div>
      {isAdding && (
        <div className="mb-4 flex gap-2">
          <input
            type="text" value={newNote} onChange={e => setNewNote(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && addNote()}
            placeholder="Escribe una nota..."
            className="flex-1 bg-[#252628] border border-[#35383d] rounded-xl px-3 py-2.5 text-white text-sm placeholder-gray-500 outline-none focus:border-[#fae0d1]/40 transition-colors"
            autoFocus
          />
          <button onClick={addNote} className="px-4 rounded-xl text-sm font-medium text-white transition-all hover:scale-105 active:scale-95" style={{ background: 'linear-gradient(135deg, #d4a574, #c4956a)' }}>
            <i className="fas fa-check"></i>
          </button>
        </div>
      )}
      <div className="space-y-2 max-h-[260px] overflow-y-auto pr-1">
        {notes.length === 0 ? (
          <div className="flex flex-col items-center py-8">
            <div className="w-14 h-14 rounded-full bg-[#252628] flex items-center justify-center mb-3"><i className="fas fa-pencil-alt text-gray-500 text-lg"></i></div>
            <p className="text-gray-400 text-sm">Agrega notas rápidas</p>
            <p className="text-gray-500 text-xs mt-1">Se guardan localmente en tu navegador</p>
          </div>
        ) : (
          notes.map(note => (
            <div key={note.id} className="flex items-start gap-3 p-3 bg-[#252628] rounded-xl group/note hover:bg-[#2a2b2f] transition-colors">
              <button onClick={() => toggleDone(note.id)} className={`w-5 h-5 rounded-md flex-shrink-0 mt-0.5 flex items-center justify-center border transition-all ${note.done ? 'bg-green-500/20 border-green-500/40' : 'border-gray-600 hover:border-[#fae0d1]/40'}`}>
                {note.done && <i className="fas fa-check text-green-400 text-[9px]"></i>}
              </button>
              <span className={`text-sm flex-1 ${note.done ? 'text-gray-500 line-through' : 'text-gray-300'}`}>{note.text}</span>
              <button onClick={() => removeNote(note.id)} className="text-gray-600 hover:text-red-400 opacity-0 group-hover/note:opacity-100 transition-all"><i className="fas fa-trash-alt text-xs"></i></button>
            </div>
          ))
        )}
      </div>
    </div>
  );
}

function CalendarWidget() {
  const [currentDate, setCurrentDate] = React.useState(new Date());
  const today = new Date();

  const year = currentDate.getFullYear();
  const month = currentDate.getMonth();
  const firstDay = new Date(year, month, 1).getDay();
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const monthNames = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
  const dayNames = ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'];

  const prevMonth = () => setCurrentDate(new Date(year, month - 1, 1));
  const nextMonth = () => setCurrentDate(new Date(year, month + 1, 1));
  const goToday = () => setCurrentDate(new Date());

  const isToday = (day) => day === today.getDate() && month === today.getMonth() && year === today.getFullYear();
  const isWeekend = (dayOfWeek) => dayOfWeek === 0 || dayOfWeek === 6;

  const cells = [];
  for (let i = 0; i < firstDay; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);

  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-rose-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-calendar-day text-rose-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Calendario</h3>
        </div>
        <button onClick={goToday} className="text-[#fae0d1] text-xs hover:underline transition-colors">Hoy</button>
      </div>
      <div className="flex items-center justify-between mb-4">
        <button onClick={prevMonth} className="w-8 h-8 rounded-lg bg-[#252628] hover:bg-[#35383d] flex items-center justify-center transition-colors"><i className="fas fa-chevron-left text-gray-400 text-xs"></i></button>
        <span className="text-white font-semibold text-sm">{monthNames[month]} {year}</span>
        <button onClick={nextMonth} className="w-8 h-8 rounded-lg bg-[#252628] hover:bg-[#35383d] flex items-center justify-center transition-colors"><i className="fas fa-chevron-right text-gray-400 text-xs"></i></button>
      </div>
      <div className="grid grid-cols-7 gap-1 mb-2">
        {dayNames.map(d => (
          <div key={d} className="text-center text-gray-500 text-xs font-medium py-1">{d}</div>
        ))}
      </div>
      <div className="grid grid-cols-7 gap-1">
        {cells.map((day, idx) => {
          if (day === null) return <div key={`e${idx}`}></div>;
          const dayOfWeek = (firstDay + day - 1) % 7;
          return (
            <div key={day} className={`text-center py-1.5 rounded-lg text-sm transition-all duration-150 cursor-default select-none ${
              isToday(day)
                ? 'bg-[#fae0d1] text-[#1b1c20] font-bold shadow-lg shadow-[#fae0d1]/20'
                : isWeekend(dayOfWeek)
                  ? 'text-gray-500 hover:bg-[#252628]'
                  : 'text-gray-300 hover:bg-[#252628]'
            }`}>
              {day}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function NotificationsWidget() {
  const [notifications, setNotifications] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    const generateNotifications = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) { setLoading(false); return; }
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }
        }, { cacheTime: 5 * 60 * 1000 });
        if (response.ok) {
          const result = await response.json();
          const tenants = (result.data || []).filter(t => t.status !== 'archived');
          const notifs = [];
          const today = new Date();

          tenants.filter(t => t.paymentStatus === 'overdue').slice(0, 3).forEach(t => {
            notifs.push({ icon: 'fas fa-exclamation-circle', color: 'text-red-400', bg: 'bg-red-500/10', title: `Pago atrasado: ${t.name}`, sub: t.apartment || 'Sin departamento', time: 'Urgente' });
          });

          tenants.filter(t => {
            const end = t.endDate || t.contractEnd;
            if (!end) return false;
            const d = new Date(end);
            return d >= today && d <= new Date(today.getTime() + 15 * 86400000);
          }).slice(0, 2).forEach(t => {
            const days = Math.ceil((new Date(t.endDate || t.contractEnd) - today) / 86400000);
            notifs.push({ icon: 'fas fa-file-contract', color: 'text-yellow-400', bg: 'bg-yellow-500/10', title: `Contrato vence en ${days}d`, sub: t.name, time: `${days} días` });
          });

          if (notifs.length === 0) {
            notifs.push({ icon: 'fas fa-check-circle', color: 'text-green-400', bg: 'bg-green-500/10', title: 'Todo en orden', sub: 'No hay alertas pendientes', time: 'Ahora' });
          }
          setNotifications(notifs);
        }
      } catch (e) { console.error('Notifications error:', e); }
      setLoading(false);
    };
    generateNotifications();
  }, []);

  return (
    <div className="bg-[#1b1c20] rounded-2xl p-7 hover-lift h-full">
      <div className="flex items-center justify-between mb-5">
        <div className="flex items-center">
          <div className="w-10 h-10 rounded-xl bg-pink-500/10 flex items-center justify-center mr-3">
            <i className="fas fa-bell text-pink-400"></i>
          </div>
          <h3 className="text-lg font-semibold text-white">Alertas</h3>
        </div>
        {notifications.length > 0 && notifications[0].title !== 'Todo en orden' && (
          <span className="bg-red-500/20 text-red-400 text-xs px-2.5 py-1 rounded-full font-medium">{notifications.length}</span>
        )}
      </div>
      {loading ? (
        <div className="py-2 space-y-3">
          <SkeletonLoader type="text" />
          <SkeletonLoader type="text" />
          <SkeletonLoader type="text" />
        </div>
      ) : (
        <div className="space-y-3 max-h-[280px] overflow-y-auto pr-1">
          {notifications.map((n, i) => (
            <div key={i} className="flex items-start gap-3 p-3 rounded-xl bg-[#252628] hover:bg-[#2a2b2f] transition-colors">
              <div className={`w-9 h-9 rounded-full ${n.bg} flex items-center justify-center flex-shrink-0`}>
                <i className={`${n.icon} ${n.color} text-sm`}></i>
              </div>
              <div className="flex-1 min-w-0">
                <p className="text-white text-sm font-medium">{n.title}</p>
                <p className="text-gray-500 text-xs mt-0.5">{n.sub}</p>
              </div>
              <span className="text-gray-500 text-xs flex-shrink-0">{n.time}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function PropertyValueWidget() {
  const [totalValue, setTotalValue] = React.useState(0);
  const [avgRent, setAvgRent] = React.useState(0);
  const [aptCount, setAptCount] = React.useState(0);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    const fetchPropertyValue = async () => {
      try {
        const organizationId = window.currentOrganizationId || localStorage.getItem('organizationId');
        if (!organizationId) { setLoading(false); return; }
        const token = getJWTFromStorage();
        const response = await cachedFetch(`http://localhost:3000/api/tenants?organizationId=${organizationId}`, {
          headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }
        }, { cacheTime: 5 * 60 * 1000 });
        if (response.ok) {
          const result = await response.json();
          const tenants = (result.data || []).filter(t => t.status !== 'archived');
          const rents = tenants.map(t => parseFloat(t.rentAmount) || 0).filter(r => r > 0);
          const sum = rents.reduce((a, b) => a + b, 0);
          setTotalValue(sum * 12);
          setAvgRent(rents.length > 0 ? Math.round(sum / rents.length) : 0);
          setAptCount(rents.length);
        }
      } catch (e) { console.error('Property value error:', e); }
      setLoading(false);
    };
    fetchPropertyValue();
  }, []);

  return (
    <div className="rounded-2xl p-7 hover-lift h-full border border-white/[0.04]" style={{ background: 'linear-gradient(135deg, var(--bg-primary), var(--bg-secondary))', backdropFilter: 'blur(20px)', boxShadow: 'var(--shadow)' }}>
      <div className="flex items-center mb-5">
        <div className="w-10 h-10 rounded-xl bg-emerald-500/10 flex items-center justify-center mr-3">
          <i className="fas fa-coins text-emerald-400"></i>
        </div>
        <h3 className="text-lg font-semibold text-white">Valor del Portafolio</h3>
      </div>
      {loading ? (
        <div className="py-4 space-y-3">
          <SkeletonLoader type="table-row" />
          <SkeletonLoader type="table-row" />
        </div>
      ) : (
        <>
          <div className="mb-6">
            <div className="text-gray-400 text-sm mb-1">Ingreso anual proyectado</div>
            <div className="text-4xl font-bold text-white">${totalValue.toLocaleString('es-MX')}</div>
          </div>
          <div className="grid grid-cols-2 gap-4">
            <div className="bg-white/[0.04] rounded-xl p-4 border border-white/[0.04]">
              <div className="text-gray-400 text-xs mb-1">Renta Promedio</div>
              <div className="text-xl font-bold text-[#fae0d1]">${avgRent.toLocaleString('es-MX')}</div>
              <div className="text-gray-500 text-xs mt-1">por unidad/mes</div>
            </div>
            <div className="bg-white/[0.04] rounded-xl p-4 border border-white/[0.04]">
              <div className="text-gray-400 text-xs mb-1">Unidades Activas</div>
              <div className="text-xl font-bold text-emerald-400">{aptCount}</div>
              <div className="text-gray-500 text-xs mt-1">con renta asignada</div>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

// ============================================
// TIPS WIDGET (extraído para registry)
// ============================================
function TipsWidget() {
  return (
    <div className="bg-[#1b1c20] rounded-2xl p-6 hover-lift h-full">
      <div className="flex items-center mb-5">
        <div className="w-10 h-10 rounded-xl bg-[#fae0d1]/10 flex items-center justify-center mr-3">
          <i className="fas fa-lightbulb text-[#fae0d1]"></i>
        </div>
        <h3 className="text-lg font-semibold text-white">Tips del Día</h3>
      </div>
      <div className="space-y-4">
        <div className="flex items-start p-4 bg-[#252628] rounded-xl hover:bg-[#35383d] transition-colors">
          <div className="w-8 h-8 rounded-full bg-blue-500/20 flex items-center justify-center flex-shrink-0 mr-3">
            <i className="fas fa-info text-blue-400 text-sm"></i>
          </div>
          <div>
            <p className="text-white text-sm font-medium">Automatiza tus recordatorios</p>
            <p className="text-gray-400 text-xs mt-1">Configura notificaciones automáticas para pagos próximos a vencer</p>
          </div>
        </div>
        <div className="flex items-start p-4 bg-[#252628] rounded-xl hover:bg-[#35383d] transition-colors">
          <div className="w-8 h-8 rounded-full bg-green-500/20 flex items-center justify-center flex-shrink-0 mr-3">
            <i className="fas fa-chart-line text-green-400 text-sm"></i>
          </div>
          <div>
            <p className="text-white text-sm font-medium">Revisa tus analíticas</p>
            <p className="text-gray-400 text-xs mt-1">Mantén un seguimiento constante de tus métricas de cobranza</p>
          </div>
        </div>
        <div className="flex items-start p-4 bg-[#252628] rounded-xl hover:bg-[#35383d] transition-colors">
          <div className="w-8 h-8 rounded-full bg-purple-500/20 flex items-center justify-center flex-shrink-0 mr-3">
            <i className="fas fa-file-contract text-purple-400 text-sm"></i>
          </div>
          <div>
            <p className="text-white text-sm font-medium">Actualiza contratos</p>
            <p className="text-gray-400 text-xs mt-1">Verifica que todos los contratos estén al día antes de su vencimiento</p>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============================================
// WIDGET REGISTRY & LAYOUT SYSTEM
// ============================================
const WIDGET_REGISTRY = {
  'welcome':            { label: 'Bienvenida',           icon: 'fas fa-sun',                defaultSpan: 6, section: 'general' },
  'quick-stats':        { label: 'Estadísticas Rápidas', icon: 'fas fa-chart-bar',          defaultSpan: 6, section: 'general' },
  'quick-actions':      { label: 'Acciones Rápidas',     icon: 'fas fa-bolt',               defaultSpan: 2, section: 'general' },
  'recent-activity':    { label: 'Actividad Reciente',   icon: 'fas fa-history',            defaultSpan: 2, section: 'general' },
  'tips':               { label: 'Tips del Día',         icon: 'fas fa-lightbulb',          defaultSpan: 3, section: 'general' },
  'calendar':           { label: 'Calendario',           icon: 'fas fa-calendar-day',       defaultSpan: 2, section: 'general' },
  'notifications':      { label: 'Alertas',              icon: 'fas fa-bell',               defaultSpan: 2, section: 'general' },
  'payment-progress':   { label: 'Progreso de Pagos',    icon: 'fas fa-chart-pie',          defaultSpan: 2, section: 'finanzas' },
  'monthly-overview':   { label: 'Resumen Mensual',      icon: 'fas fa-calendar',           defaultSpan: 4, section: 'finanzas' },
  'upcoming-payments':  { label: 'Vencimientos',         icon: 'fas fa-calendar-alt',       defaultSpan: 3, section: 'finanzas' },
  'payment-summary':    { label: 'Resumen de Pagos',     icon: 'fas fa-file-invoice-dollar', defaultSpan: 6, section: 'finanzas' },
  'property-value':     { label: 'Valor del Portafolio', icon: 'fas fa-coins',              defaultSpan: 6, section: 'finanzas' },
  'occupancy':          { label: 'Tasa de Ocupación',    icon: 'fas fa-building',           defaultSpan: 3, section: 'gestion' },
  'contract-status':    { label: 'Estado de Contratos',  icon: 'fas fa-file-contract',      defaultSpan: 3, section: 'gestion' },
  'system-status':      { label: 'Estado del Sistema',   icon: 'fas fa-server',             defaultSpan: 2, section: 'herramientas' },
  'quick-notes':        { label: 'Notas Rápidas',        icon: 'fas fa-sticky-note',        defaultSpan: 2, section: 'herramientas' },
};

const WIDGET_SECTIONS = {
  general:      { label: 'General',       icon: 'fas fa-th-large',       color: 'text-blue-400' },
  finanzas:     { label: 'Finanzas',      icon: 'fas fa-dollar-sign',    color: 'text-green-400' },
  gestion:      { label: 'Gestión',       icon: 'fas fa-tasks',          color: 'text-purple-400' },
  herramientas: { label: 'Herramientas',  icon: 'fas fa-tools',          color: 'text-orange-400' },
};

const DEFAULT_LAYOUT = [
  { id: 'welcome', span: 6 },
  { id: 'quick-stats', span: 6 },
  { id: 'quick-actions', span: 2 },
  { id: 'recent-activity', span: 2 },
  { id: 'payment-progress', span: 2 },
  { id: 'monthly-overview', span: 4 },
  { id: 'system-status', span: 2 },
  { id: 'upcoming-payments', span: 3 },
  { id: 'tips', span: 3 },
  { id: 'payment-summary', span: 6 },
];

const LAYOUT_STORAGE_KEY = 'esperiency_dashboard_layout';

function loadDashboardLayout() {
  try {
    const saved = localStorage.getItem(LAYOUT_STORAGE_KEY);
    if (saved) {
      const parsed = JSON.parse(saved);
      if (Array.isArray(parsed) && parsed.length > 0 && parsed.every(item => item.id && WIDGET_REGISTRY[item.id])) {
        return parsed;
      }
    }
  } catch (e) { console.error('Error loading dashboard layout:', e); }
  return DEFAULT_LAYOUT.map(item => ({ ...item }));
}

function saveDashboardLayout(layout) {
  try { localStorage.setItem(LAYOUT_STORAGE_KEY, JSON.stringify(layout)); }
  catch (e) { console.error('Error saving dashboard layout:', e); }
}

function renderWidgetContent(widgetId, setCurrentPage) {
  switch (widgetId) {
    case 'welcome':           return React.createElement(WelcomeWidget);
    case 'quick-stats':       return React.createElement(QuickStatsWidget, { setCurrentPage });
    case 'quick-actions':     return React.createElement(QuickActionsWidget, { setCurrentPage });
    case 'recent-activity':   return React.createElement(RecentActivityWidget);
    case 'payment-progress':  return React.createElement(PaymentProgressWidget);
    case 'monthly-overview':  return React.createElement(MonthlyOverviewWidget);
    case 'system-status':     return React.createElement(SystemStatusWidget);
    case 'upcoming-payments': return React.createElement(UpcomingPaymentsWidget);
    case 'tips':              return React.createElement(TipsWidget);
    case 'payment-summary':   return React.createElement(PaymentSummaryWidget);
    case 'occupancy':         return React.createElement(OccupancyWidget);
    case 'contract-status':   return React.createElement(ContractStatusWidget);
    case 'quick-notes':       return React.createElement(QuickNotesWidget);
    case 'calendar':          return React.createElement(CalendarWidget);
    case 'notifications':     return React.createElement(NotificationsWidget);
    case 'property-value':    return React.createElement(PropertyValueWidget);
    default: return null;
  }
}

const SPAN_CLASSES = {
  1: 'col-span-6 lg:col-span-1',
  2: 'col-span-6 lg:col-span-2',
  3: 'col-span-6 lg:col-span-3',
  4: 'col-span-6 lg:col-span-4',
  5: 'col-span-6 lg:col-span-5',
  6: 'col-span-6',
};

const SPAN_LABELS = { 1: '1/6', 2: '2/6', 3: '3/6', 4: '4/6', 5: '5/6', 6: '6/6' };

// ============================================
// DASHBOARD WIDGETS - CUSTOMIZABLE LAYOUT
// ============================================
function DraggableWidgetGrid({ setCurrentPage, layout, setLayout, defaultLayout, widgetRegistry, saveLayout, renderWidgetContentFn, emptyMessage = "Clic o arrastra un widget aquí" }) {
  const containerRef = React.useRef(null);
  const [isCustomizing, setIsCustomizing] = React.useState(false);
  const [savedLayout, setSavedLayout] = React.useState(null);
  const [draggedIdx, setDraggedIdx] = React.useState(null);
  const [dragOverIdx, setDragOverIdx] = React.useState(null);
  const [hasChanges, setHasChanges] = React.useState(false);
  const [dockOpen, setDockOpen] = React.useState(false);
  const [emptySlotPicker, setEmptySlotPicker] = React.useState(null); // { insertAtIdx, slotSpan } — widget picker for empty slot click

  // Expose global function to enter customize mode
  React.useEffect(() => {
    window.enterCustomizeMode = () => {
      setSavedLayout(layout.map(item => ({ ...item })));
      setIsCustomizing(true);
      setHasChanges(false);
      setDockOpen(false);
    };
    return () => { delete window.enterCustomizeMode; };
  }, [layout]);

  // GSAP entrance animation (only on first render, not during customization)
  const hasAnimated = React.useRef(false);
  const ensureWidgetsVisible = React.useCallback(() => {
    if (!containerRef.current) return;
    containerRef.current.querySelectorAll('.gsap-widget').forEach((el) => {
      el.style.opacity = '1';
      el.style.transform = 'none';
    });
  }, []);

  React.useEffect(() => {
    if (!containerRef.current || isCustomizing || hasAnimated.current) return;
    hasAnimated.current = true;
    const widgets = containerRef.current.querySelectorAll('.gsap-widget');
    if (!widgets.length) return;

    if (typeof gsap === 'undefined') {
      ensureWidgetsVisible();
      return;
    }

    gsap.set(widgets, { opacity: 0, y: 40, scale: 0.95 });
    gsap.to(widgets, { opacity: 1, y: 0, scale: 1, duration: 0.7, stagger: 0.1, ease: 'power3.out', clearProps: 'all' });
  }, [isCustomizing, ensureWidgetsVisible]);

  React.useEffect(() => {
    if (!containerRef.current) return;
    const t = setTimeout(ensureWidgetsVisible, 600);
    return () => clearTimeout(t);
  }, [layout, isCustomizing, ensureWidgetsVisible]);

  // GSAP animation when entering customize mode
  const prevCustomizing = React.useRef(false);
  React.useEffect(() => {
    if (typeof gsap === 'undefined' || !containerRef.current) return;
    // Entering customize mode
    if (isCustomizing && !prevCustomizing.current) {
      const topBar = containerRef.current.parentElement?.querySelector('.cust-topbar');
      if (topBar) {
        gsap.fromTo(topBar, { opacity: 0, y: -8 }, { opacity: 1, y: 0, duration: 0.3, ease: 'power2.out' });
      }
      const widgets = containerRef.current.querySelectorAll('.gsap-widget');
      gsap.fromTo(widgets, { opacity: 0.7 }, {
        opacity: 1, duration: 0.25, stagger: 0.02, ease: 'power2.out', clearProps: 'opacity'
      });
      const emptySlots = containerRef.current.querySelectorAll('.cust-empty-slot');
      gsap.fromTo(emptySlots, { opacity: 0 }, {
        opacity: 1, duration: 0.3, stagger: 0.03, ease: 'power2.out', delay: 0.1
      });
      const dock = document.querySelector('.cust-dock');
      if (dock) {
        gsap.fromTo(dock, { y: 20, opacity: 0 }, { y: 0, opacity: 1, duration: 0.3, ease: 'power2.out', delay: 0.1 });
      }
      // Auto-expand dock after entrance animation
      setTimeout(() => setDockOpen(true), 400);
    }
    if (!isCustomizing && prevCustomizing.current) {
      const widgets = containerRef.current.querySelectorAll('.gsap-widget');
      gsap.to(widgets, { opacity: 1, duration: 0.2, ease: 'power2.out', clearProps: 'all' });
    }
    prevCustomizing.current = isCustomizing;
  }, [isCustomizing]);

  // Available widgets not currently in layout
  const availableWidgets = Object.keys(widgetRegistry).filter(id => !layout.some(item => item.id === id));

  // Track what's being dragged from dock
  const dockDragId = React.useRef(null);

  // ===== Compute grid rows and empty slots =====
  // Walks through layout items, tracks column usage per row,
  // and emits empty-slot entries wherever there's leftover space.
  const computeRenderItems = () => {
    const items = [];
    let col = 0; // current column position in a 6-col row
    layout.forEach((item, idx) => {
      const span = Math.min(item.span, 6);
      if (col + span > 6) {
        // Widget overflows — fill remaining space with empty slot
        const gap = 6 - col;
        if (gap > 0) {
          items.push({ type: 'empty', span: gap, insertAtIdx: idx, rowCol: col });
        }
        col = 0;
      }
      items.push({ type: 'widget', id: item.id, span: span, layoutIdx: idx });
      col += span;
      if (col >= 6) col = 0;
    });
    // Trailing empty space
    if (col > 0 && col < 6) {
      items.push({ type: 'empty', span: 6 - col, insertAtIdx: layout.length, rowCol: col });
    }
    return items;
  };
  const renderItems = computeRenderItems();

  // Compute available columns at a given layout index (for auto-fit)
  const getAvailableSpanAt = (insertIdx) => {
    // Simulate layout up to insertIdx to know current row position
    let col = 0;
    for (let i = 0; i < layout.length && i < insertIdx; i++) {
      const s = Math.min(layout[i].span, 6);
      col += s;
      if (col >= 6) col = 0;
    }
    return col === 0 ? 6 : 6 - col;
  };

  // Drag handlers (widget reorder)
  const handleDragStart = (e, idx) => {
    dockDragId.current = null;
    setDraggedIdx(idx);
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', idx.toString());
    requestAnimationFrame(() => { if (e.target) e.target.style.opacity = '0.5'; });
  };

  const handleDragEnd = (e) => {
    e.target.style.opacity = '1';
    setDraggedIdx(null);
    setDragOverIdx(null);
    dockDragId.current = null;
  };

  const handleDragOver = (e, idx) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    if (draggedIdx !== null && idx !== draggedIdx) setDragOverIdx(idx);
    if (dockDragId.current) setDragOverIdx(idx);
  };

  const handleDragLeave = () => { setDragOverIdx(null); };

  // Unified drop handler — works for widget-on-widget, widget-on-empty, dock-on-widget, dock-on-empty
  const handleDrop = (e, dropIdx, isEmptySlot, slotSpan) => {
    e.preventDefault();
    e.stopPropagation();

    const animateDropSuccess = () => {
      if (typeof gsap === 'undefined' || !containerRef.current) return;
      requestAnimationFrame(() => {
        const allWidgets = containerRef.current.querySelectorAll('.gsap-widget');
        const target = allWidgets[dropIdx] || allWidgets[allWidgets.length - 1];
        if (target) {
          gsap.fromTo(target, { opacity: 0.7 }, { opacity: 1, duration: 0.25, ease: 'power2.out', clearProps: 'opacity' });
        }
      });
    };

    // --- DOCK WIDGET (new widget from bottom dock) ---
    if (dockDragId.current) {
      const widgetId = dockDragId.current;
      dockDragId.current = null;
      if (!widgetRegistry[widgetId]) return;
      const reg = widgetRegistry[widgetId];
      let span = reg.defaultSpan;
      if (isEmptySlot && slotSpan) {
        span = Math.min(span, slotSpan); // auto-fit to empty slot
      } else {
        // Dropping on a widget — auto-fit to available space at that position
        const avail = getAvailableSpanAt(dropIdx);
        if (avail < span && avail > 0) span = avail;
      }
      const newLayout = [...layout];
      newLayout.splice(dropIdx, 0, { id: widgetId, span });
      setLayout(newLayout);
      setHasChanges(true);
      setDragOverIdx(null);
      animateDropSuccess();
      return;
    }

    // --- REORDER (existing widget dragged) ---
    if (draggedIdx === null || draggedIdx === dropIdx) return;
    const newLayout = [...layout];
    const [moved] = newLayout.splice(draggedIdx, 1);

    if (isEmptySlot && slotSpan) {
      // Auto-fit: shrink widget to slot if it's larger
      moved.span = Math.min(moved.span, slotSpan);
    } else {
      // Auto-fit to remaining columns at drop position
      const adjustedIdx = draggedIdx < dropIdx ? dropIdx - 1 : dropIdx;
      // Simulate column usage up to adjustedIdx in newLayout (without the moved item)
      let col = 0;
      for (let i = 0; i < adjustedIdx && i < newLayout.length; i++) {
        col += Math.min(newLayout[i].span, 6);
        if (col >= 6) col = col % 6;
      }
      const avail = col === 0 ? 6 : 6 - col;
      if (moved.span > avail) moved.span = avail;
    }

    // Adjust insertIdx since we removed before it
    const adjustedIdx = draggedIdx < dropIdx ? dropIdx - 1 : dropIdx;
    newLayout.splice(adjustedIdx, 0, moved);
    setLayout(newLayout);
    setHasChanges(true);
    setDraggedIdx(null);
    setDragOverIdx(null);
    animateDropSuccess();
  };

  const removeWidget = (idx) => {
    if (typeof gsap !== 'undefined' && containerRef.current) {
      const widgets = containerRef.current.querySelectorAll('.gsap-widget');
      const target = widgets[idx];
      if (target) {
        gsap.to(target, {
          opacity: 0, duration: 0.2, ease: 'power2.in',
          onComplete: () => {
            setLayout(prev => prev.filter((_, i) => i !== idx));
            setHasChanges(true);
          }
        });
        return;
      }
    }
    setLayout(layout.filter((_, i) => i !== idx));
    setHasChanges(true);
  };

  const resizeWidget = (idx, newSpan) => {
    const clamped = Math.max(1, Math.min(6, newSpan));
    setLayout(layout.map((item, i) => i === idx ? { ...item, span: clamped } : item));
    setHasChanges(true);
  };

  const addWidget = (widgetId) => {
    const reg = widgetRegistry[widgetId];
    if (!reg) return;
    setLayout([...layout, { id: widgetId, span: reg.defaultSpan }]);
    setHasChanges(true);
    if (typeof gsap !== 'undefined' && containerRef.current) {
      requestAnimationFrame(() => {
        const widgets = containerRef.current.querySelectorAll('.gsap-widget');
        const last = widgets[widgets.length - 1];
        if (last) gsap.fromTo(last, { opacity: 0 }, { opacity: 1, duration: 0.3, ease: 'power2.out', clearProps: 'opacity' });
      });
    }
  };

  // Add widget at a specific position (for empty slot click picker)
  const addWidgetAt = (widgetId, atIdx, fitSpan) => {
    const reg = widgetRegistry[widgetId];
    if (!reg) return;
    const span = fitSpan ? Math.min(reg.defaultSpan, fitSpan) : reg.defaultSpan;
    const newLayout = [...layout];
    newLayout.splice(atIdx, 0, { id: widgetId, span });
    setLayout(newLayout);
    setHasChanges(true);
    setEmptySlotPicker(null);
    if (typeof gsap !== 'undefined' && containerRef.current) {
      requestAnimationFrame(() => {
        const widgets = containerRef.current.querySelectorAll('.gsap-widget');
        const target = widgets[atIdx] || widgets[widgets.length - 1];
        if (target) gsap.fromTo(target, { opacity: 0 }, { opacity: 1, duration: 0.3, ease: 'power2.out', clearProps: 'opacity' });
      });
    }
  };

  const handleSave = () => {
    saveLayout(layout);
    setSavedLayout(null);
    setIsCustomizing(false);
    setHasChanges(false);
  };

  const handleCancel = () => {
    if (savedLayout) setLayout(savedLayout);
    setSavedLayout(null);
    setIsCustomizing(false);
    setHasChanges(false);
  };

  const handleReset = () => {
    setLayout(defaultLayout.map(item => ({ ...item })));
    setHasChanges(true);
  };

  // GSAP: animate dock widgets when dock opens
  React.useEffect(() => {
    if (!dockOpen || typeof gsap === 'undefined') return;
    requestAnimationFrame(() => {
      const dockItems = document.querySelectorAll('.cust-dock-item');
      if (dockItems.length) {
        gsap.fromTo(dockItems, { opacity: 0 }, {
          opacity: 1, duration: 0.2, stagger: 0.02, ease: 'power2.out', clearProps: 'opacity'
        });
      }
    });
  }, [dockOpen, availableWidgets.length]);

  // Close empty slot picker when layout changes
  React.useEffect(() => { setEmptySlotPicker(null); }, [layout]);

  return (
    <div className={`relative ${isCustomizing ? 'pb-72' : ''}`}>
      {/* ===== Customize Mode Top Bar ===== */}
      {isCustomizing && (
        <div
          className="cust-topbar sticky top-0 z-50 mb-6 flex items-center justify-between px-5 py-3 rounded-2xl"
          style={{ background: 'var(--bg-glass)', backdropFilter: 'blur(24px)', boxShadow: 'var(--shadow-lg)', border: '1px solid var(--border-primary)' }}
        >
          <div className="flex items-center gap-3">
            <div className="w-9 h-9 rounded-xl flex items-center justify-center" style={{ background: 'var(--accent-bg)' }}>
              <i className="fas fa-palette" style={{ color: 'var(--accent)' }}></i>
            </div>
            <div>
              <div className="font-semibold text-sm" style={{ color: 'var(--text-primary)' }}>Modo Personalización</div>
              <div className="text-xs" style={{ color: 'var(--text-muted)' }}>Arrastra para mover · Suelta en espacios vacíos · Redimensiona abajo · ✕ para quitar</div>
            </div>
          </div>
          <div className="flex items-center gap-2">
            <button onClick={handleReset} className="px-3 py-2 rounded-xl text-sm transition-all duration-200" style={{ color: 'var(--text-tertiary)' }}
              onMouseOver={(e) => { e.currentTarget.style.color = 'var(--text-primary)'; e.currentTarget.style.background = 'var(--bg-hover)'; }}
              onMouseOut={(e) => { e.currentTarget.style.color = 'var(--text-tertiary)'; e.currentTarget.style.background = 'transparent'; }}
            >
              <i className="fas fa-undo mr-1.5"></i>Restablecer
            </button>
            <button onClick={handleCancel} className="px-3 py-2 rounded-xl text-sm transition-all duration-200" style={{ color: 'var(--text-tertiary)' }}
              onMouseOver={(e) => { e.currentTarget.style.color = 'var(--text-primary)'; e.currentTarget.style.background = 'var(--bg-hover)'; }}
              onMouseOut={(e) => { e.currentTarget.style.color = 'var(--text-tertiary)'; e.currentTarget.style.background = 'transparent'; }}
            >
              Cancelar
            </button>
            {hasChanges && (
              <button
                onClick={handleSave}
                className="cust-save-btn px-5 py-2 rounded-xl text-white text-sm font-semibold transition-all duration-200 hover:brightness-110 active:scale-[0.98] animate-[fadeSlideIn_0.2s_ease-out]"
                style={{ background: 'linear-gradient(135deg, var(--accent) 0%, var(--accent-hover) 100%)', boxShadow: '0 4px 20px rgba(212,165,116,0.25)' }}
              >
                <i className="fas fa-save mr-2"></i>Guardar
              </button>
            )}
          </div>
        </div>
      )}

      {/* ===== Widget Grid (6-column) ===== */}
      <div ref={containerRef} className="grid grid-cols-6 gap-7">
        {renderItems.map((ri, renderIdx) => {
          // ===== Empty slot placeholder =====
          if (ri.type === 'empty') {
            const spanClass = SPAN_CLASSES[ri.span] || 'col-span-6';
            if (!isCustomizing) return null; // Only show in customize mode
            const isPickerOpen = emptySlotPicker && emptySlotPicker.insertAtIdx === ri.insertAtIdx;
            const pickerWidgets = Object.keys(widgetRegistry).filter(id => !layout.some(item => item.id === id));
            return (
              <div
                key={`empty-${renderIdx}`}
                className={`cust-empty-slot ${spanClass} min-h-[120px] rounded-2xl border-2 border-dashed transition-all duration-300 flex flex-col items-center justify-center cursor-pointer group/empty ${
                  isPickerOpen ? 'border-[#fae0d1]/50 bg-[#fae0d1]/[0.04]' : 'border-white/[0.06] hover:border-[#fae0d1]/30 hover:bg-[#fae0d1]/[0.02]'
                }`}
                onClick={() => {
                  if (isPickerOpen) { setEmptySlotPicker(null); }
                  else { setEmptySlotPicker({ insertAtIdx: ri.insertAtIdx, slotSpan: ri.span }); }
                }}
                onDragOver={(e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; e.currentTarget.classList.add('border-[#fae0d1]/50', 'bg-[#fae0d1]/[0.04]', 'scale-[1.02]'); }}
                onDragLeave={(e) => { e.currentTarget.classList.remove('border-[#fae0d1]/50', 'bg-[#fae0d1]/[0.04]', 'scale-[1.02]'); }}
                onDrop={(e) => { e.currentTarget.classList.remove('border-[#fae0d1]/50', 'bg-[#fae0d1]/[0.04]', 'scale-[1.02]'); handleDrop(e, ri.insertAtIdx, true, ri.span); }}
              >
                {!isPickerOpen ? (
                  <>
                    <div className="w-10 h-10 rounded-xl bg-white/[0.03] flex items-center justify-center mb-2 group-hover/empty:bg-[#fae0d1]/10 transition-all duration-300 group-hover/empty:scale-110">
                      <i className="fas fa-plus text-gray-600 group-hover/empty:text-[#fae0d1]/60 transition-colors"></i>
                    </div>
                    <span className="text-gray-600 text-xs group-hover/empty:text-gray-400 transition-colors">Espacio libre · {ri.span} col</span>
                    <span className="text-gray-700 text-[10px] mt-0.5">{emptyMessage}</span>
                  </>
                ) : (
                  <div className="w-full p-3" onClick={(e) => e.stopPropagation()}>
                    <div className="flex items-center justify-between mb-2">
                      <span className="text-[#fae0d1] text-xs font-semibold">Seleccionar widget</span>
                      <button onClick={() => setEmptySlotPicker(null)} className="text-gray-500 hover:text-white text-xs transition-colors">
                        <i className="fas fa-times"></i>
                      </button>
                    </div>
                    {pickerWidgets.length === 0 ? (
                      <div className="text-gray-500 text-xs text-center py-2">No hay widgets disponibles</div>
                    ) : (
                      <div className="grid grid-cols-2 gap-1.5 max-h-[200px] overflow-y-auto">
                        {pickerWidgets.map(wId => {
                          const reg = widgetRegistry[wId];
                          return (
                            <button
                              key={wId}
                              onClick={() => addWidgetAt(wId, ri.insertAtIdx, ri.span)}
                              className="flex items-center gap-2 px-2.5 py-2 rounded-lg bg-white/[0.03] hover:bg-[#fae0d1]/10 border border-transparent hover:border-[#fae0d1]/20 transition-all duration-200 text-left group/pick hover:scale-[1.02]"
                            >
                              <i className={`${reg.icon} text-[#fae0d1]/60 group-hover/pick:text-[#fae0d1] text-xs transition-colors`}></i>
                              <span className="text-gray-400 group-hover/pick:text-white text-[10px] truncate transition-colors">{reg.label}</span>
                            </button>
                          );
                        })}
                      </div>
                    )}
                  </div>
                )}
              </div>
            );
          }

          // ===== Regular widget =====
          const item = { id: ri.id, span: ri.span };
          const idx = ri.layoutIdx;
          const spanClass = SPAN_CLASSES[item.span] || 'col-span-6';
          const isDragTarget = dragOverIdx === idx && draggedIdx !== idx;
          const isDockDragTarget = dragOverIdx === idx && dockDragId.current;

          return (
            <div
              key={item.id}
              className={`gsap-widget ${spanClass} h-full transition-all duration-200 ${
                isCustomizing ? 'relative group/cust cursor-grab active:cursor-grabbing' : ''
              } ${isDragTarget || isDockDragTarget ? 'ring-1 ring-[#fae0d1]/30 ring-offset-1 ring-offset-[#18181b]' : ''} ${
                draggedIdx === idx ? 'opacity-50' : ''
              }`}
              draggable={isCustomizing}
              onDragStart={isCustomizing ? (e) => handleDragStart(e, idx) : undefined}
              onDragEnd={isCustomizing ? handleDragEnd : undefined}
              onDragOver={isCustomizing ? (e) => handleDragOver(e, idx) : undefined}
              onDragLeave={isCustomizing ? handleDragLeave : undefined}
              onDrop={isCustomizing ? (e) => handleDrop(e, idx, false) : undefined}
            >
              {/* Customize overlay controls */}
              {isCustomizing && (
                <>
                  <div className="absolute inset-0 border-2 border-dashed border-white/10 rounded-2xl pointer-events-none z-10 group-hover/cust:border-[#fae0d1]/40 transition-colors duration-200"></div>
                  {/* Top label */}
                  <div className="absolute top-3 left-1/2 -translate-x-1/2 z-20 bg-[#1b1c20]/95 border border-white/[0.08] rounded-lg px-3 py-1.5 flex items-center gap-2 opacity-0 group-hover/cust:opacity-100 transition-all duration-200 shadow-xl pointer-events-none select-none">
                    <i className="fas fa-grip-vertical text-gray-500 text-xs"></i>
                    <span className="text-gray-400 text-xs font-medium">{widgetRegistry[item.id]?.label}</span>
                  </div>
                  {/* Remove button */}
                  <button
                    onClick={(e) => { e.stopPropagation(); removeWidget(idx); }}
                    className="absolute -top-2.5 -right-2.5 z-20 w-7 h-7 rounded-full bg-red-500/90 hover:bg-red-500 text-white flex items-center justify-center opacity-0 group-hover/cust:opacity-100 transition-all duration-200 hover:scale-110 shadow-lg"
                  >
                    <i className="fas fa-times text-xs"></i>
                  </button>
                  {/* Resize controls */}
                  <div className="absolute bottom-3 left-1/2 -translate-x-1/2 z-20 bg-[#1b1c20]/95 border border-white/[0.08] rounded-xl flex items-center gap-0 opacity-0 group-hover/cust:opacity-100 transition-all duration-200 shadow-xl overflow-hidden">
                    <button
                      onClick={(e) => { e.stopPropagation(); resizeWidget(idx, item.span - 1); }}
                      disabled={item.span <= 1}
                      className={`px-2.5 py-1.5 text-xs transition-colors ${item.span <= 1 ? 'text-gray-700 cursor-not-allowed' : 'text-gray-400 hover:text-white hover:bg-white/[0.08]'}`}
                    >
                      <i className="fas fa-compress-alt"></i>
                    </button>
                    <div className="flex items-center gap-1 px-2 border-x border-white/[0.06]">
                      {[1,2,3,4,5,6].map(s => (
                        <button
                          key={s}
                          onClick={(e) => { e.stopPropagation(); resizeWidget(idx, s); }}
                          className={`w-5 h-5 rounded text-[9px] font-bold transition-all duration-150 ${item.span === s ? 'bg-[#fae0d1] text-[#1b1c20]' : 'text-gray-500 hover:text-white hover:bg-white/[0.08]'}`}
                        >{s}</button>
                      ))}
                    </div>
                    <button
                      onClick={(e) => { e.stopPropagation(); resizeWidget(idx, item.span + 1); }}
                      disabled={item.span >= 6}
                      className={`px-2.5 py-1.5 text-xs transition-colors ${item.span >= 6 ? 'text-gray-700 cursor-not-allowed' : 'text-gray-400 hover:text-white hover:bg-white/[0.08]'}`}
                    >
                      <i className="fas fa-expand-alt"></i>
                    </button>
                  </div>
                </>
              )}
              {renderWidgetContentFn(item.id, setCurrentPage)}
            </div>
          );
        })}
      </div>

      {/* ===== Sticky Bottom Dock: Available Widgets by Section ===== */}
      {isCustomizing && (
        <div
          className="cust-dock fixed bottom-0 left-0 right-0 z-50 border-t border-white/[0.08]"
          style={{ background: 'var(--bg-glass)', backdropFilter: 'blur(24px)', boxShadow: 'var(--shadow-lg)' }}
        >
          <button
            onClick={() => setDockOpen(!dockOpen)}
            className="w-full flex items-center justify-between px-6 py-3 hover:bg-white/[0.02] transition-colors"
          >
            <div className="flex items-center gap-2">
              <i className="fas fa-puzzle-piece text-[#fae0d1]"></i>
              <span className="text-white text-sm font-semibold">Widgets Disponibles</span>
              {availableWidgets.length > 0 && (
                <span className="bg-[#fae0d1]/20 text-[#fae0d1] text-xs px-2 py-0.5 rounded-full font-medium">{availableWidgets.length}</span>
              )}
            </div>
            <i className={`fas fa-chevron-up text-gray-500 text-xs transition-transform duration-300 ${dockOpen ? 'rotate-180' : ''}`}></i>
          </button>

          <div
            className="overflow-hidden transition-all duration-400 ease-in-out"
            style={{ maxHeight: dockOpen ? '45vh' : '0px', opacity: dockOpen ? 1 : 0, transition: 'max-height 0.4s cubic-bezier(0.4,0,0.2,1), opacity 0.3s ease' }}
          >
            <div className="px-6 pb-5 overflow-y-auto" style={{ maxHeight: '45vh' }}>
              <div className="space-y-5">
                {/* Themes section */}
                <div>
                  <div className="flex items-center gap-2 mb-3">
                    <i className="fas fa-palette text-[#fae0d1] text-xs"></i>
                    <span className="text-gray-400 text-xs font-semibold uppercase tracking-wider">Temas</span>
                    <div className="flex-1 h-px bg-white/[0.06]"></div>
                  </div>
                  <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-4 gap-2.5">
                    {Object.keys(THEMES).map(id => (
                      <ThemeDockCard key={id} themeId={id} layout={layout} />
                    ))}
                  </div>
                </div>
                {availableWidgets.length === 0 ? (
                  <div className="text-center py-4">
                    <i className="fas fa-check-circle text-green-400 text-xl mb-1"></i>
                    <p className="text-gray-400 text-sm">Todos los widgets están en el dashboard</p>
                  </div>
                ) : (
                  <>
                  {Object.entries(WIDGET_SECTIONS).map(([sectionKey, section]) => {
                    const sectionWidgets = availableWidgets.filter(id => widgetRegistry[id]?.section === sectionKey);
                    if (sectionWidgets.length === 0) return null;
                    return (
                      <div key={sectionKey}>
                        <div className="flex items-center gap-2 mb-3">
                          <i className={`${section.icon} ${section.color} text-xs`}></i>
                          <span className="text-gray-400 text-xs font-semibold uppercase tracking-wider">{section.label}</span>
                          <div className="flex-1 h-px bg-white/[0.06]"></div>
                          <span className="text-gray-600 text-xs">{sectionWidgets.length}</span>
                        </div>
                        <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 gap-2.5">
                          {sectionWidgets.map(widgetId => {
                            const reg = widgetRegistry[widgetId];
                            return (
                              <div
                                key={widgetId}
                                draggable
                                onDragStart={(e) => {
                                  e.dataTransfer.effectAllowed = 'move';
                                  e.dataTransfer.setData('text/plain', widgetId);
                                  dockDragId.current = widgetId;
                                  setDraggedIdx(null);
                                }}
                                onDragEnd={() => { dockDragId.current = null; }}
                                onClick={() => addWidget(widgetId)}
                                className="cust-dock-item flex items-center gap-2.5 p-2.5 rounded-xl bg-[#1b1c20] hover:bg-[#252628] border border-white/[0.04] hover:border-[#fae0d1]/30 transition-all duration-200 group/add hover:scale-[1.03] cursor-grab active:cursor-grabbing active:scale-95"
                              >
                                <div className="w-8 h-8 rounded-lg bg-[#fae0d1]/10 flex items-center justify-center flex-shrink-0">
                                  <i className={`${reg.icon} text-[#fae0d1] text-sm`}></i>
                                </div>
                                <span className="text-gray-300 text-xs text-left flex-1 truncate">{reg.label}</span>
                                <i className="fas fa-grip-lines text-gray-600 group-hover/add:text-[#fae0d1] text-[10px] transition-colors"></i>
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    );
                  })}
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}


function DashboardWidgets({ setCurrentPage }) {
  const [layout, setLayout] = React.useState(() => loadDashboardLayout());
  return (
    <DraggableWidgetGrid 
      setCurrentPage={setCurrentPage}
      layout={layout}
      setLayout={setLayout}
      defaultLayout={DEFAULT_LAYOUT}
      widgetRegistry={WIDGET_REGISTRY}
      saveLayout={saveDashboardLayout}
      renderWidgetContentFn={renderWidgetContent}
    />
  );
}

function SidebarRight({ setSidebarExpanded, isCollapsed, setIsCollapsed }) {
  const [selectedIcon, setSelectedIcon] = React.useState(0); 
  const [currentPage, setCurrentPage] = React.useState(0);
  const [selectedTask, setSelectedTask] = React.useState(null);
  const [isModalOpen, setIsModalOpen] = React.useState(false);

  const toggleSidebar = () => {
    setIsCollapsed(!isCollapsed);
  };
  
  const extendedNotifications = [];

  const regularNotifications = [];

  const itemsPerPage = 4;
  const currentData = selectedIcon === 0 ? extendedNotifications : regularNotifications;
  const totalPages = Math.ceil(currentData.length / itemsPerPage);
  const startIndex = currentPage * itemsPerPage;
  const currentItems = currentData.slice(startIndex, startIndex + itemsPerPage);

  React.useEffect(() => {
    if (setSidebarExpanded) {
      setSidebarExpanded(true);
    }
  }, [setSidebarExpanded]);

  React.useEffect(() => {
    setCurrentPage(0);
  }, [selectedIcon]);

  return (
    <>
      <div className={`fixed inset-y-0 right-0 px-4 pb-4 pt-2 hidden xl:block flex flex-col transition-all duration-300 ease-in-out ${isCollapsed ? 'w-16' : 'w-64'}`} style={{ background: 'var(--bg-body)' }}>

      <div className="flex items-center justify-end mb-4 flex-shrink-0">
        <div 
          className="size-8 rounded-full grid place-items-center border-2 border-[#252628] text-white cursor-pointer hover:bg-[#252628] transition-colors"
          onClick={toggleSidebar}
        >
          <svg className={`size-5 transition-transform duration-300 ${isCollapsed ? 'rotate-180' : ''}`} strokeWidth={3} viewBox="0 0 24 24" fill="none" stroke="currentColor">
            <path d="m9 18 6-6-6-6"/>
          </svg>
        </div>
      </div>

      {!isCollapsed ? (
        <>

          <div className="flex items-center justify-center pb-4 border-b-2 border-b-zinc-800 flex-shrink-0">
        {rightSidebarItems.map(({ Icon }, idx) => (
          <button
            onClick={() => {
              setSelectedIcon(idx);
            }}
            className={`mx-2 transition-all duration-200 hover:bg-opacity-90 ${
              selectedIcon === idx 
                ? "size-12 grid place-items-center rounded-lg bg-[#fae0d1] text-[#1b1c20] shadow-lg" 
                : "p-3 text-[#666] hover:text-white"
            }`}
            key={idx}
          >
            <Icon />
          </button>
        ))}
      </div>
      

      <div className="flex flex-col flex-1 mt-4 overflow-hidden h-full">

        <div className="text-white font-semibold mb-4 text-center flex-shrink-0">
          {selectedIcon === 0 ? "Tareas" : "Notificaciones"}
        </div>
        

        <div className="flex flex-col space-y-2 flex-1 overflow-hidden">
          {currentItems.map((item, idx) => {
            if (selectedIcon === 0) {
              const { title, time, category } = item;
              let borderClass = "";
              let timeColorClass = "";
              let categoryColorClass = "";
              
              if (time === "Muy alta") {
                borderClass = "border-2 border-red-600";
                timeColorClass = "text-red-500 font-bold";
                categoryColorClass = "text-red-300";
              } else if (time === "Alta") {
                borderClass = "border-2 border-orange-500";
                timeColorClass = "text-orange-400 font-semibold";
                categoryColorClass = "text-orange-300";
              } else {
                borderClass = "";
                timeColorClass = "text-[#70718e]";
                categoryColorClass = "text-[#5b5b5b]";
              }
              
              return (
                <div
                  className={`p-0.5 rounded-md transition-all duration-200 hover:bg-opacity-90 cursor-pointer ${borderClass}`}
                  key={idx}
                  onClick={() => {
                    setSelectedTask(item);
                    setIsModalOpen(true);
                  }}
                >
                  <div className="bg-zinc-950 p-3 rounded-md">
                    <div className={timeColorClass}>{time}</div>
                    <div className="mt-1 font-semibold text-white">{title}</div>
                    <div className={`mt-2 ${categoryColorClass}`}>{category}</div>
                  </div>
                </div>
              );
            } else {
              const { title, time, category, icon } = item;
              return (
                <div
                  className="p-0.5 rounded-md transition-all duration-200 hover:bg-opacity-90"
                  key={idx}
                >
                  <div className="bg-zinc-950 p-3 rounded-md">
                    <div className="flex items-center justify-between">
                      <div className="text-[#70718e] text-sm">{time}</div>
                      <div className="text-lg">{icon}</div>
                    </div>
                    <div className="mt-1 font-semibold text-white">{title}</div>
                    <div className="mt-2 text-[#5b5b5b] text-sm">{category}</div>
                  </div>
                </div>
              );
            }
          })}
        </div>
        

        {totalPages > 1 && (
          <div className="flex items-center justify-center mt-4 space-x-2 flex-shrink-0">
            <button
              onClick={() => setCurrentPage(Math.max(0, currentPage - 1))}
              disabled={currentPage === 0}
              className="size-8 grid place-items-center rounded-md bg-[#35383d] text-white hover:bg-[#4a4d52] disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200"
            >
              <svg className="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M15 18l-6-6 6-6"/>
              </svg>
            </button>
            
            <div className="flex space-x-1">
              {Array.from({ length: totalPages }, (_, i) => (
                <button
                  key={i}
                  onClick={() => setCurrentPage(i)}
                  className={`size-8 grid place-items-center rounded-md text-sm font-medium transition-all duration-200 ${
                    currentPage === i
                      ? "bg-[#fae0d1] text-[#1b1c20]"
                      : "bg-[#35383d] text-white hover:bg-[#4a4d52]"
                  }`}
                >
                  {i + 1}
                </button>
              ))}
            </div>
            
            <button
              onClick={() => setCurrentPage(Math.min(totalPages - 1, currentPage + 1))}
              disabled={currentPage === totalPages - 1}
              className="size-8 grid place-items-center rounded-md bg-[#35383d] text-white hover:bg-[#4a4d52] disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200"
            >
              <svg className="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M9 18l6-6-6-6"/>
              </svg>
            </button>
          </div>
        )}
      </div>
        </>
      ) : (

        <div className="flex flex-col items-center space-y-4 pt-4">
          {rightSidebarItems.map(({ Icon }, idx) => (
            <button
              onClick={() => {
                setSelectedIcon(idx);
                setIsCollapsed(false); 
              }}
              className={`transition-all duration-200 hover:bg-opacity-90 ${
                selectedIcon === idx 
                  ? "size-10 grid place-items-center rounded-lg bg-[#fae0d1] text-[#1b1c20] shadow-lg" 
                  : "size-10 grid place-items-center text-[#666] hover:text-white hover:bg-[#252628] rounded-lg"
              }`}
              key={idx}
            >
              <Icon />
            </button>
          ))}
        </div>
      )}
    </div>

      {isModalOpen && selectedTask && (
        <div className="fixed inset-0 flex items-center justify-center z-50">

          <div 
            className="absolute inset-0 bg-black/20 backdrop-blur-md"
            onClick={() => setIsModalOpen(false)}
          />
          
          <div className="relative bg-[#1b1c20] border border-[#35383d] rounded-2xl shadow-2xl p-10 max-w-4xl w-full mx-4 text-white">
            <div className="flex justify-between items-start mb-8">
              <div className="flex items-center gap-4">
                <h3 className="text-3xl font-bold text-white">{selectedTask.title}</h3>
                <div className={`inline-block px-5 py-2 rounded-full text-base font-semibold ${
                  selectedTask.priority === 'Muy alta' ? 'bg-red-500/20 text-red-300 border border-red-500/30' :
                  selectedTask.priority === 'Alta' ? 'bg-orange-500/20 text-orange-300 border border-orange-500/30' :
                  selectedTask.priority === 'Media' ? 'bg-yellow-500/20 text-yellow-300 border border-yellow-500/30' :
                  'bg-gray-500/20 text-gray-300 border border-gray-500/30'
                }`}>
                  {selectedTask.priority}
                </div>
              </div>
              <button
                onClick={() => setIsModalOpen(false)}
                className="text-[#666] hover:text-white transition-colors p-2"
              >
                <svg className="size-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            </div>
            
            <div className="space-y-8">
              <div>
                <h4 className="font-semibold text-white mb-4 text-xl">Descripción</h4>
                <p className="text-[#b0b0b0] text-lg leading-relaxed">{selectedTask.description}</p>
              </div>
              
              <div className="grid grid-cols-2 gap-8">
                <div>
                  <h4 className="font-semibold text-white mb-3 text-lg">Creada por</h4>
                  <p className="text-[#b0b0b0] text-lg">{selectedTask.assignedTo}</p>
                </div>
                <div>
                  <h4 className="font-semibold text-white mb-3 text-lg">Estado</h4>
                  <p className="text-[#b0b0b0] text-lg">{selectedTask.status}</p>
                </div>
              </div>
              
              <div>
                <h4 className="font-semibold text-white mb-3 text-lg">Categoría</h4>
                <p className="text-[#b0b0b0] text-lg">{selectedTask.category}</p>
              </div>
            </div>
            <div className="flex justify-end mt-10">
              <button className="flex items-center gap-3 px-8 py-4 bg-green-800 hover:bg-green-700 text-white rounded-lg transition-colors font-medium text-lg">
                <i className="fas fa-check"></i>
                Marcar como completada
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

function Graph() {
  const drawn = React.useRef(false);

  React.useEffect(() => {
    if (!drawn.current) {
      drawn.current = true;
      drawGraph();
    }
  }, []);

  return (
    <div className="px-4">
      <div className="flex items-center">
        <svg className="size-5 text-[#606165]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          <path d="M3 3v18h18" />
          <path d="M18.7 8l-5.1 5.2-2.8-2.7L7 14.3" />
        </svg>
        <div className="text-base font-semibold ml-2 text-white">Reportes</div>
        <div className="ml-auto inline-flex items-center space-x-2 p-1 rounded-md bg-[#1b1c20]">
          <button className="w-16 bg-white text-[#1b1c20] rounded-md py-0.5 cursor-pointer text-sm font-semibold">
            24h
          </button>
          <button className="w-16 rounded-md py-0.5 cursor-pointer text-white text-sm">
            7d
          </button>
          <button className="w-16 rounded-md py-0.5 cursor-pointer text-white text-sm">
            1m
          </button>
        </div>
      </div>
      <div
        className="min-h-[175px] mt-2 bg-[#1b1c20] rounded-md"
        id="graph-container"
      ></div>
    </div>
  );
}

function drawPaymentGraph() {
  const ctx = document.getElementById('payment-graph-container');
  if (ctx && typeof Chart !== 'undefined') {
    ctx.innerHTML = '';
    const canvas = document.createElement('canvas');
    canvas.style.width = '100%';
    canvas.style.height = '300px';
    ctx.appendChild(canvas);
    
    if (paymentData.length === 0) {
      new Chart(canvas, {
        type: 'line',
        data: {
          labels: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
          datasets: [
            {
              label: 'Inquilinos que Pagaron',
              data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              borderColor: '#fae0d1',
              backgroundColor: 'rgba(250, 224, 209, 0.1)',
              tension: 0.4,
              fill: true,
            },
            {
              label: 'Total Apartamentos',
              data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              borderColor: '#666',
              backgroundColor: 'rgba(102, 102, 102, 0.05)',
              borderDash: [5, 5],
            }
          ]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: {
              display: true,
              labels: {
                color: '#fff'
              }
            }
          },
          scales: {
            x: {
              grid: {
                display: false
              },
              ticks: {
                color: '#666'
              }
            },
            y: {
              grid: {
                color: '#333'
              },
              ticks: {
                color: '#666'
              },
              beginAtZero: true,
              max: 10
            }
          }
        }
      });
      return;
    }
    
    const currentMonthIndex = paymentData.findIndex(d => d.current);
    const pointColors = paymentData.map((_, index) => 
      index === currentMonthIndex ? '#ff6b6b' : '#fae0d1'
    );
    const pointSizes = paymentData.map((_, index) => 
      index === currentMonthIndex ? 8 : 4
    );
    
    new Chart(canvas, {
      type: 'line',
      data: {
        labels: paymentData.map(d => d.month),
        datasets: [
          {
            label: 'Inquilinos que Pagaron',
            data: paymentData.map(d => d.paid),
            borderColor: '#fae0d1',
            backgroundColor: 'rgba(250, 224, 209, 0.1)',
            tension: 0.4,
            fill: true,
            pointBackgroundColor: pointColors,
            pointBorderColor: pointColors,
            pointRadius: pointSizes,
            pointHoverRadius: pointSizes.map(size => size + 2),
          },
          {
            label: 'Total Apartamentos',
            data: paymentData.map(d => d.total),
            borderColor: '#666',
            backgroundColor: 'rgba(102, 102, 102, 0.05)',
            borderDash: [5, 5],
            pointBackgroundColor: '#666',
            pointBorderColor: '#666',
            pointRadius: 2,
          }
        ]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: {
            display: true,
            labels: {
              color: '#fff'
            }
          },
          tooltip: {
            callbacks: {
              afterLabel: function(context) {
                const dataIndex = context.dataIndex;
                if (paymentData[dataIndex].current) {
                  return 'Mes Actual';
                }
                return '';
              }
            }
          }
        },
        scales: {
          x: {
            grid: {
              display: false
            },
            ticks: {
              color: function(context) {
                const index = context.index;
                return paymentData[index] && paymentData[index].current ? '#ff6b6b' : '#666';
              },
              font: function(context) {
                const index = context.index;
                return {
                  weight: paymentData[index] && paymentData[index].current ? 'bold' : 'normal'
                };
              }
            }
          },
          y: {
            grid: {
              color: '#333'
            },
            ticks: {
              color: '#666'
            },
            beginAtZero: true,
            max: 55
          }
        }
      }
    });
  }
}

function drawIngresosGraph() {
  const ctx = document.getElementById('ingresos-graph-container');
  if (ctx && typeof Chart !== 'undefined') {
    ctx.innerHTML = '';
    const canvas = document.createElement('canvas');
    canvas.style.width = '100%';
    canvas.style.height = '300px';
    ctx.appendChild(canvas);
    
    if (ingresosData.length === 0) {
      new Chart(canvas, {
        type: 'bar',
        data: {
          labels: ['Sin datos'],
          datasets: [{
            label: 'Ingresos',
            data: [0],
            backgroundColor: 'rgba(250, 224, 209, 0.3)',
            borderColor: '#fae0d1',
            borderWidth: 2,
            borderRadius: 4,
          }]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: {
              display: false
            }
          },
          scales: {
            x: {
              grid: {
                display: false
              },
              ticks: {
                color: '#666'
              }
            },
            y: {
              grid: {
                color: '#333'
              },
              ticks: {
                color: '#666',
                callback: function(value) {
                  return '$' + value.toLocaleString('es-MX');
                }
              },
              beginAtZero: true,
              max: 4000
            }
          }
        }
      });
      return;
    }
    
    new Chart(canvas, {
      type: 'bar',
      data: {
        labels: ingresosData.map(d => d.apartment),
        datasets: [{
          label: 'Ingresos',
          data: ingresosData.map(d => d.amount),
          backgroundColor: [
            'rgba(250, 224, 209, 0.8)',
            'rgba(196, 135, 126, 0.8)',
            'rgba(217, 193, 179, 0.8)',
            'rgba(172, 154, 198, 0.8)',
            'rgba(250, 224, 209, 0.6)',
            'rgba(196, 135, 126, 0.6)',
            'rgba(217, 193, 179, 0.6)',
            'rgba(172, 154, 198, 0.6)',
          ],
          borderColor: [
            '#fae0d1',
            '#c4877e',
            '#d9c1b3',
            '#ac9ac6',
            '#fae0d1',
            '#c4877e',
            '#d9c1b3',
            '#ac9ac6',
          ],
          borderWidth: 2,
          borderRadius: 4,
        }]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: {
            display: false
          },
          tooltip: {
            callbacks: {
              label: function(context) {
                return 'Ingresos: $' + context.parsed.y.toLocaleString('es-MX');
              }
            }
          }
        },
        scales: {
          x: {
            grid: {
              display: false
            },
            ticks: {
              color: '#666'
            }
          },
          y: {
            grid: {
              color: '#333'
            },
            ticks: {
              color: '#666',
              callback: function(value) {
                return '$' + value.toLocaleString('es-MX');
              }
            },
            beginAtZero: true
          }
        }
      }
    });
  }
}

function drawGraph() {
  const ctx = document.getElementById('graph-container');
  if (ctx && typeof Chart !== 'undefined') {
    ctx.innerHTML = '';
    const canvas = document.createElement('canvas');
    canvas.style.width = '100%';
    canvas.style.height = '175px';
    ctx.appendChild(canvas);
    
    new Chart(canvas, {
      type: 'line',
      data: {
        labels: ['6AM', '9AM', '12PM', '3PM', '6PM', '9PM'],
        datasets: [{
          label: 'Reportes',
          data: [12, 19, 3, 5, 2, 3],
          borderColor: '#fae0d1',
          backgroundColor: 'rgba(250, 224, 209, 0.1)',
          tension: 0.4,
          fill: true
        }]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: {
            display: false
          }
        },
        scales: {
          x: {
            grid: {
              display: false
            },
            ticks: {
              color: '#666'
            }
          },
          y: {
            grid: {
              color: '#333'
            },
            ticks: {
              color: '#666'
            }
          }
        }
      }
    });
  }
}

function Status() {
  return (
    <div className="grid grid-cols-3 gap-3 mt-2 px-4">
      {statusItems.map(
        ({ title, count, percentage, color1, color2, Icon }, idx) => (
          <div className="p-3 rounded-md bg-[#1b1c20]" key={idx}>
            <div className="flex items-center space-x-2">
              <div className="font-semibold text-white">{title}</div>
              <div className="grid place-items-center size-5 bg-[#28292d] rounded-full text-[#65666b]">
                <svg className="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                  <circle cx="12" cy="12" r="10"/>
                  <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/>
                  <path d="M12 17h.01"/>
                </svg>
              </div>
            </div>

            <div className="flex items-center space-x-3 mt-2">
              <div
                className="size-9 grid place-items-center rounded-full text-[#3c3c55]"
                style={{ background: color1 }}
              >
                <Icon />
              </div>
              <div className="text-lg text-white font-semibold">{count.toLocaleString('es-MX')}</div>
              <div
                className="py-0.5 px-2 rounded-md text-white text-sm font-semibold"
                style={{ background: color2 }}
              >
                +{percentage}%
              </div>
            </div>
          </div>
        )
      )}
    </div>
  );
}

const App = () => {
  const [sidebarExpanded, setSidebarExpanded] = React.useState(true);
  const [sidebarLeftCollapsed, setSidebarLeftCollapsed] = React.useState(() => {
    const saved = localStorage.getItem('esperiency_sidebar_left_collapsed');
    return saved === 'true';
  });
  const [sidebarRightCollapsed, setSidebarRightCollapsed] = React.useState(() => {
    const saved = localStorage.getItem('esperiency_sidebar_right_collapsed');
    return saved === 'true';
  });
  const [currentPage, setCurrentPage] = React.useState('dashboard'); 
  const [appLoading, setAppLoading] = React.useState(true);
  const [pageTransition, setPageTransition] = React.useState(false);

  React.useEffect(() => {
    localStorage.setItem('esperiency_sidebar_left_collapsed', sidebarLeftCollapsed);
  }, [sidebarLeftCollapsed]);

  React.useEffect(() => {
    localStorage.setItem('esperiency_sidebar_right_collapsed', sidebarRightCollapsed);
  }, [sidebarRightCollapsed]);
  
  const handlePageChange = (newPage) => {
    if (newPage === currentPage) return;
    setPageTransition(true);
    setTimeout(() => {
      setCurrentPage(newPage);
      setPageTransition(false);
    }, 600); // 600ms transition
  };

  React.useEffect(() => {
    window.setCurrentPage = handlePageChange;
  }, [currentPage]);
  
  React.useEffect(() => {
    const timer = setTimeout(() => {
      setAppLoading(false);
    }, 2000);
    return () => clearTimeout(timer);
  }, []);
  
  return (
    <div style={{ position: 'relative', zIndex: 1 }}>
      <PageTransitionLoader isVisible={pageTransition} />
      
      <SidebarLeft 
        isCollapsed={sidebarLeftCollapsed}
        setIsCollapsed={setSidebarLeftCollapsed}
        currentPage={currentPage}
        setCurrentPage={handlePageChange}
      />
      <SidebarRight 
        setSidebarExpanded={setSidebarExpanded}
        isCollapsed={sidebarRightCollapsed}
        setIsCollapsed={setSidebarRightCollapsed}
      />
      <div className={`transition-all duration-500 pl-0 pr-0 ${
        sidebarLeftCollapsed ? 'xl:pl-16' : 'xl:pl-64'
      } ${
        sidebarRightCollapsed ? 'xl:pr-16' : (sidebarExpanded ? 'xl:pr-80' : 'xl:pr-64')
      }`}>
        {appLoading ? (
          <div className="flex items-center justify-center h-full min-h-[calc(100vh-48px)]">
            <GreyLogoLoader text="CARGANDO" />
          </div>
        ) : (
          <div className="max-w-none mx-auto py-6 px-6">
            <div className="mb-6">
              <GlobalSearchBar onNavigate={handlePageChange} />
            </div>
            
            {currentPage === 'dashboard' && (
              <DashboardWidgets setCurrentPage={handlePageChange} />
            )}
            
            {currentPage === 'inquilinos' && TenantsPage && <TenantsPage />}
            {currentPage === 'add-tenant' && AddTenantPage && <AddTenantPage />}
            {currentPage === 'analitica' && (
              <AnalyticsWidgets setCurrentPage={handlePageChange} />
            )}
            {currentPage === 'departamentos' && <ApartmentsPage setCurrentPage={setCurrentPage} />}
            {currentPage === 'add-apartment' && window.AddApartmentPage && (
              <AddApartmentPage onCancel={() => setCurrentPage('departamentos')} />
            )}
            {currentPage === 'administrar' && window.AdminPage && <AdminPage />}
            
            {currentPage === 'tareas' && (
              <PlaceholderPage 
                title="Tareas" 
                icon="fas fa-tasks" 
                color="blue"
                description="Gestiona y asigna tareas de mantenimiento, cobranza y seguimiento a tu equipo."
                setCurrentPage={setCurrentPage}
              />
            )}
            {currentPage === 'mantenimiento' && (
              <PlaceholderPage 
                title="Mantenimiento" 
                icon="fas fa-wrench" 
                color="yellow"
                description="Registra solicitudes de mantenimiento, da seguimiento a reparaciones y programa servicios preventivos."
                setCurrentPage={setCurrentPage}
              />
            )}
            {currentPage === 'soporte' && (
              <PlaceholderPage 
                title="Soporte" 
                icon="fas fa-headset" 
                color="purple"
                description="Centro de ayuda y soporte técnico. Crea tickets, consulta guías y contacta al equipo de soporte."
                setCurrentPage={setCurrentPage}
              />
            )}
            {currentPage === 'chat' && (
              <PlaceholderPage 
                title="Mensajes" 
                icon="fas fa-comments" 
                color="green"
                description="Comunicación directa con inquilinos y equipo de administración en tiempo real."
                setCurrentPage={setCurrentPage}
              />
            )}
            {currentPage === 'configuracion' && (
              <PlaceholderPage 
                title="Configuración" 
                icon="fas fa-cog" 
                color="gray"
                description="Personaliza tu organización, notificaciones, permisos de usuario y preferencias del sistema."
                setCurrentPage={setCurrentPage}
              />
            )}
          </div>
        )}
      </div>
    </div>
  );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(React.createElement(ThemeProvider, null, React.createElement(App)));
