
// ============================================
// 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="flex items-center justify-center min-h-[400px] w-full">
            <MiniLoader size={60} text="Cargando departamentos" />
          </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>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  );
};

// Componente Mini Loader con logo animado - animación CSS pura ultra fluida
const MiniLoader = ({ size = 40, text = '' }) => {
  return (
    <div className="flex flex-col items-center justify-center gap-4">
      <style>{`
        @keyframes loaderFloat1 {
          0%, 100% { transform: translate(0, 0); }
          25% { transform: translate(2px, -2px); }
          50% { transform: translate(0, -3px); }
          75% { transform: translate(-2px, -2px); }
        }
        @keyframes loaderFloat2 {
          0%, 100% { transform: translate(0, 0); }
          25% { transform: translate(-2px, 2px); }
          50% { transform: translate(0, 3px); }
          75% { transform: translate(2px, 2px); }
        }
        @keyframes loaderPulse {
          0%, 100% { opacity: 0.6; }
          50% { opacity: 1; }
        }
        .loader-svg-1 {
          animation: loaderFloat1 2s ease-in-out infinite, loaderPulse 2s ease-in-out infinite;
        }
        .loader-svg-2 {
          animation: loaderFloat2 2s ease-in-out infinite, loaderPulse 2s ease-in-out infinite 0.5s;
        }
        @keyframes dotBounce {
          0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
          40% { opacity: 1; transform: translateY(-3px); }
        }
        .loader-dot-1 { animation: dotBounce 1.4s ease-in-out infinite; }
        .loader-dot-2 { animation: dotBounce 1.4s ease-in-out infinite 0.2s; }
        .loader-dot-3 { animation: dotBounce 1.4s ease-in-out infinite 0.4s; }
      `}</style>
      <div style={{position: 'relative', width: size, height: size}}>
        <svg className="loader-svg-1" xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 1024 1024" 
          style={{position: 'absolute', top: 0, left: 0}}>
          <path style={{ fill: 'var(--text-tertiary, #9ca3af)' }} d="M 470.5,230.5 C 520.501,230.333 570.501,230.5 620.5,231C 641.629,238.423 649.129,252.923 643,274.5C 638.017,285.471 629.517,291.971 617.5,294C 572.5,294.333 527.5,294.667 482.5,295C 475.585,296.291 469.252,298.958 463.5,303C 434.031,330.134 404.865,357.634 376,385.5C 368.667,397.833 368.667,410.167 376,422.5C 387.839,435.57 401.672,438.07 417.5,430C 451.468,399.034 485.134,367.7 518.5,336C 537.119,325.206 552.952,328.372 566,345.5C 571.158,357.487 570.491,369.154 564,380.5C 530.167,412.333 496.333,444.167 462.5,476C 427.826,502.567 391.159,505.567 352.5,485C 311.585,455.627 298.752,416.794 314,368.5C 317.657,359.844 322.324,351.844 328,344.5C 359.167,314.667 390.333,284.833 421.5,255C 435.731,242.551 452.064,234.385 470.5,230.5 Z"/>
        </svg>
        <svg className="loader-svg-2" xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 1024 1024" 
          style={{position: 'absolute', top: 0, left: 0}}>
          <path style={{ fill: 'var(--text-muted, #6b7280)' }} d="M 606.5,416.5 C 648.301,412.155 680.468,427.488 703,462.5C 721.528,499.533 719.194,535.199 696,569.5C 661.789,603.378 626.623,636.211 590.5,668C 578.451,675.239 565.451,679.906 551.5,682C 501.5,682.667 451.5,682.667 401.5,682C 383.06,675.304 375.227,662.137 378,642.5C 382.007,629.828 390.507,621.995 403.5,619C 451.532,618.971 499.532,618.304 547.5,617C 552.945,615.112 557.945,612.445 562.5,609C 590.635,583.2 618.468,557.033 646,530.5C 655.961,514.422 654.461,499.588 641.5,486C 628.805,477.389 616.138,477.389 603.5,486C 568.768,519.402 533.434,552.069 497.5,584C 478.272,592.462 463.438,587.629 453,569.5C 447.086,553.242 450.919,539.742 464.5,529C 498.468,498.034 532.134,466.7 565.5,435C 578.021,426.069 591.688,419.902 606.5,416.5 Z"/>
        </svg>
      </div>
      {text && (
        <div className="text-sm font-light tracking-wider flex items-center" style={{ color: 'var(--text-tertiary, #9ca3af)' }}>
          {text}
          <span className="ml-1 flex">
            <span className="loader-dot-1">.</span>
            <span className="loader-dot-2">.</span>
            <span className="loader-dot-3">.</span>
          </span>
        </div>
      )}
    </div>
  );
};

// Componente de Loader Centrado para usar en cualquier página
const CenteredLoader = ({ text = 'Cargando', size = 60, fullScreen = false }) => {
  const containerClass = fullScreen 
    ? 'fixed inset-0 z-50'
    : 'w-full h-full min-h-[200px]';
  
  return (
    <div className={`${containerClass} flex items-center justify-center`} style={fullScreen ? { background: 'var(--bg-glass)', backdropFilter: 'blur(12px)' } : undefined}>
      <MiniLoader size={size} text={text} />
    </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
    document.cookie = 'authToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
    document.cookie = 'isLoggedIn=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
    document.cookie = 'userEmail=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
  } 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
    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' };
      }
    }
    
    // 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.error('❌ userData corrupto: no es un objeto');
          return { valid: false, reason: 'CORRUPT_USER_DATA' };
        }
        // Verificar que el email coincida con el del token
        if (userData.email && payload.email && userData.email !== payload.email) {
          console.error('❌ Datos inconsistentes: email no coincide');
          return { valid: false, reason: 'DATA_MISMATCH' };
        }
      } catch (parseError) {
        console.error('❌ userData corrupto: JSON inválido');
        return { valid: false, reason: 'CORRUPT_USER_DATA_JSON' };
      }
    }
    
    // 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(() => {
      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();
        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="flex items-center justify-center py-8">
            <MiniLoader size={40} />
          </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">
              <MiniLoader size={50} />
            </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="flex items-center justify-center py-8">
          <MiniLoader size={40} />
        </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-center justify-center h-48">
          <MiniLoader size={50} />
        </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">
            <MiniLoader size={60} />
            <p className="text-gray-400 mt-4">{status.title}</p>
          </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="flex items-center justify-center py-12">
          <MiniLoader size={50} />
        </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>
  );
}

// ============================================
// NUEVOS WIDGETS - GESTIÓN Y HERRAMIENTAS
// ============================================

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="flex items-center justify-center py-10"><MiniLoader size={40} /></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="flex items-center justify-center py-8"><MiniLoader size={40} /></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="flex items-center justify-center py-8"><MiniLoader size={40} /></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="flex items-center justify-center py-10"><MiniLoader size={40} /></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 DashboardWidgets({ setCurrentPage }) {
  const containerRef = React.useRef(null);
  const [layout, setLayout] = React.useState(() => loadDashboardLayout());
  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(WIDGET_REGISTRY).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 (!WIDGET_REGISTRY[widgetId]) return;
      const reg = WIDGET_REGISTRY[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 = WIDGET_REGISTRY[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 = WIDGET_REGISTRY[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 = () => {
    saveDashboardLayout(layout);
    setSavedLayout(null);
    setIsCustomizing(false);
    setHasChanges(false);
  };

  const handleCancel = () => {
    if (savedLayout) setLayout(savedLayout);
    setSavedLayout(null);
    setIsCustomizing(false);
    setHasChanges(false);
  };

  const handleReset = () => {
    setLayout(DEFAULT_LAYOUT.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(WIDGET_REGISTRY).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">Clic o arrastra un widget aquí</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 = WIDGET_REGISTRY[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">{WIDGET_REGISTRY[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>
                </>
              )}
              {renderWidgetContent(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 => WIDGET_REGISTRY[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 = WIDGET_REGISTRY[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 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);
  // Cargar estado colapsado desde localStorage
  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);

  // Guardar estado del sidebar izquierdo en localStorage
  React.useEffect(() => {
    localStorage.setItem('esperiency_sidebar_left_collapsed', sidebarLeftCollapsed);
  }, [sidebarLeftCollapsed]);

  // Guardar estado del sidebar derecho en localStorage
  React.useEffect(() => {
    localStorage.setItem('esperiency_sidebar_right_collapsed', sidebarRightCollapsed);
  }, [sidebarRightCollapsed]);
  
  // Hacer setCurrentPage disponible globalmente
  React.useEffect(() => {
    window.setCurrentPage = setCurrentPage;
  }, []);
  
  // Simular carga inicial de la app
  React.useEffect(() => {
    const timer = setTimeout(() => {
      setAppLoading(false);
    }, 2000);
    return () => clearTimeout(timer);
  }, []);
  
  return (
    <div style={{ position: 'relative', zIndex: 1 }}>
      <SidebarLeft 
        isCollapsed={sidebarLeftCollapsed}
        setIsCollapsed={setSidebarLeftCollapsed}
        currentPage={currentPage}
        setCurrentPage={setCurrentPage}
      />
      <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)]">
            <MiniLoader size={100} text="CARGANDO" />
          </div>
        ) : (
          <div className="max-w-none mx-auto py-6 px-6">
            {currentPage === 'dashboard' && (
              <DashboardWidgets setCurrentPage={setCurrentPage} />
            )}
            
            {currentPage === 'inquilinos' && TenantsPage && <TenantsPage />}
            {currentPage === 'add-tenant' && AddTenantPage && <AddTenantPage />}
            {currentPage === 'analitica' && window.AnalyticsDashboard && <AnalyticsDashboard />}
            {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)));
