// ============================
// LELUSA — App Bootstrap
// src/app/app.jsx
// ============================

const THEMES = {
  floral: { name: 'Floral Delicado', primary: '#C4899A', primaryDark: '#9E6B7C', primaryLight: '#EDD8E0', accent: '#D4A0A0', accentLight: '#F4EAEC' },
  boho:   { name: 'Boho Calido', primary: '#B8865A', primaryDark: '#8F6540', primaryLight: '#F0E4D4', accent: '#D4B08A', accentLight: '#F4EAD8' },
  luxury: { name: 'Luxury Dorado', primary: '#C8A87A', primaryDark: '#A08050', primaryLight: '#F4ECDC', accent: '#D4BEA0', accentLight: '#F4EEE0' },
};

function applyTheme(name) {
  const t = THEMES[name] || THEMES.floral;
  const r = document.documentElement;
  r.style.setProperty('--primary', t.primary);
  r.style.setProperty('--primary-dark', t.primaryDark);
  r.style.setProperty('--primary-light', t.primaryLight);
  r.style.setProperty('--accent', t.accent);
  r.style.setProperty('--accent-light', t.accentLight);
}

const TWEAK_DEFAULTS = {
  theme: 'luxury',
  roundness: 'soft',
};

const ROUTE_BY_PAGE = {
  home: () => '/',
  catalog: () => '/catalogo',
  'deco-detail': data => `/catalogo/${data.decoId || ''}`,
  customizer: data => `/personalizar/${data.decoId || ''}`,
  'quote-form': data => `/cotizador/${data.decoId || ''}`,
  'admin-dashboard': () => '/admin',
  'admin-quotes': () => '/admin/cotizaciones',
  'admin-designs': () => '/admin/decoraciones',
  'admin-desserts': () => '/admin/postres',
  'admin-team': () => '/admin/equipo',
  'admin-calendar': () => '/admin/calendario',
  'admin-event-detail': data => `/admin/eventos/${data.eventId || ''}`,
  'admin-email': () => '/admin/email',
  'admin-finance': () => '/admin/finanzas',
  'admin-inventory': () => '/admin/inventario',
  'admin-postera': () => '/admin/postera',
  'admin-settings': () => '/admin/configuracion',
  'admin-scene-editor': data => `/admin/decoraciones/${data.designId || ''}/editor`,
};

function getSearchData(search) {
  const params = new URLSearchParams(search);
  const data = {};

  params.forEach((value, key) => {
    data[key] = value;
  });

  return data;
}

function getRouteFromLocation() {
  const path = window.location.pathname.replace(/\/+$/, '') || '/';
  const queryData = getSearchData(window.location.search);

  if (path === '/' || path === '/Lelusa.html' || path === '/index.html') {
    return { page: 'home', data: queryData };
  }

  if (path === '/catalogo') {
    return { page: 'catalog', data: queryData };
  }

  let match = path.match(/^\/catalogo\/([^/]+)$/);
  if (match) {
    return { page: 'deco-detail', data: { ...queryData, decoId: decodeURIComponent(match[1]) } };
  }

  match = path.match(/^\/personalizar(?:\/([^/]+))?$/);
  if (match) {
    return { page: 'customizer', data: { ...queryData, decoId: match[1] ? decodeURIComponent(match[1]) : queryData.decoId } };
  }

  match = path.match(/^\/cotizador(?:\/([^/]+))?$/);
  if (match) {
    return { page: 'quote-form', data: { ...queryData, decoId: match[1] ? decodeURIComponent(match[1]) : queryData.decoId } };
  }

  if (path === '/admin') return { page: 'admin-dashboard', data: queryData };
  if (path === '/admin/cotizaciones') return { page: 'admin-quotes', data: queryData };
  if (path === '/admin/decoraciones' || path === '/admin/disenos') return { page: 'admin-designs', data: queryData };
  if (path === '/admin/postres') return { page: 'admin-desserts', data: queryData };
  if (path === '/admin/equipo' || path === '/admin/usuarios') return { page: 'admin-team', data: queryData };
  if (path === '/admin/calendario') return { page: 'admin-calendar', data: queryData };
  match = path.match(/^\/admin\/eventos\/([^/]+)$/);
  if (match) {
    return { page: 'admin-event-detail', data: { ...queryData, eventId: decodeURIComponent(match[1]) } };
  }
  if (path === '/admin/email') return { page: 'admin-email', data: queryData };
  if (path === '/admin/finanzas') return { page: 'admin-finance', data: queryData };
  if (path === '/admin/inventario') return { page: 'admin-inventory', data: queryData };
  if (path === '/admin/postera' || path === '/admin/tools/postera') return { page: 'admin-postera', data: queryData };
  if (path === '/admin/configuracion') return { page: 'admin-settings', data: queryData };

  match = path.match(/^\/admin\/(?:decoraciones|disenos)\/([^/]+)\/editor$/);
  if (match) {
    return { page: 'admin-scene-editor', data: { ...queryData, designId: decodeURIComponent(match[1]) } };
  }

  return { page: 'home', data: queryData };
}

function getUrlForPage(page, data = {}) {
  const createPath = ROUTE_BY_PAGE[page] || ROUTE_BY_PAGE.home;
  const path = createPath(data).replace(/\/+$/, '') || '/';
  const params = new URLSearchParams();
  const pathKeys = new Set(['decoId', 'designId', 'eventId']);

  Object.entries(data).forEach(([key, value]) => {
    if (pathKeys.has(key) || value == null || typeof value === 'object') return;
    params.set(key, String(value));
  });

  const search = params.toString();
  return search ? `${path}?${search}` : path;
}

function normalizeUrlPath(url) {
  const parsed = new URL(url, window.location.origin);
  return `${parsed.pathname.replace(/\/+$/, '') || '/'}${parsed.search}`;
}

const ADMIN_PROFILE_KEY = 'lelusa.admin.profile.v1';
const ADMIN_USERS_KEY = 'lelusa.admin.users.v1';
const ADMIN_SESSION_KEY = 'lelusa.admin.session.v1';
const ADMIN_SESSION_TTL_MS = 12 * 60 * 60 * 1000;

const ADMIN_PERMISSION_LABELS = {
  dashboard: 'Dashboard',
  quotes: 'Cotizaciones',
  decorations: 'Decoraciones',
  desserts: 'Postres',
  calendar: 'Calendario',
  finance: 'Finanzas',
  inventory: 'Inventario',
  tools: 'Herramientas',
  team: 'Equipo',
  settings: 'Configuración',
  notify: 'Enviar notificaciones',
};

const ADMIN_PAGE_PERMISSION = {
  'admin-dashboard': 'dashboard',
  'admin-quotes': 'quotes',
  'admin-designs': 'decorations',
  'admin-scene-editor': 'decorations',
  'admin-desserts': 'desserts',
  'admin-calendar': 'calendar',
  'admin-event-detail': 'calendar',
  'admin-finance': 'finance',
  'admin-inventory': 'inventory',
  'admin-postera': 'tools',
  'admin-team': 'team',
  'admin-settings': 'settings',
  'admin-send-notification': 'notify',
};

const ALL_ADMIN_PERMISSIONS = Object.keys(ADMIN_PERMISSION_LABELS);

function getDefaultPermissions(role = 'staff', department = 'decoracion') {
  if (role === 'owner') return ALL_ADMIN_PERMISSIONS;
  const base = ['dashboard', 'calendar'];
  const byDepartment = {
    direccion: ['quotes', 'decorations', 'desserts', 'finance', 'inventory', 'tools', 'team', 'settings'],
    decoracion: ['quotes', 'decorations', 'inventory', 'tools'],
    postres: ['quotes', 'desserts', 'inventory'],
    finanzas: ['quotes', 'finance'],
    operaciones: ['quotes', 'inventory'],
  };
  const managerExtra = role === 'manager' ? ['team'] : [];
  return Array.from(new Set([...base, ...(byDepartment[department] || []), ...managerExtra]));
}

function normalizePermissions(user) {
  if (user?.role === 'owner') return ALL_ADMIN_PERMISSIONS;
  const permissions = Array.isArray(user?.permissions) ? user.permissions : [];
  return permissions.length ? permissions.filter(item => ALL_ADMIN_PERMISSIONS.includes(item)) : getDefaultPermissions(user?.role, user?.department);
}

function canAccessAdminPage(user, page) {
  if (!isAdminPage(page)) return true;
  if (!user || user.active === false) return false;
  if (user.role === 'owner') return true;
  const needed = ADMIN_PAGE_PERMISSION[page];
  if (!needed) return true;
  return normalizePermissions(user).includes(needed);
}

window.LelusaAccess = {
  labels: ADMIN_PERMISSION_LABELS,
  all: ALL_ADMIN_PERMISSIONS,
  pagePermission: ADMIN_PAGE_PERMISSION,
  getDefaultPermissions,
  normalizePermissions,
  canAccessPage: canAccessAdminPage,
};

function isAdminPage(page) {
  return String(page || '').startsWith('admin-');
}

async function hashAdminPassword(value) {
  const bytes = new TextEncoder().encode(value);
  const digest = await crypto.subtle.digest('SHA-256', bytes);
  return Array.from(new Uint8Array(digest)).map(byte => byte.toString(16).padStart(2, '0')).join('');
}

function readAdminProfile() {
  try {
    const raw = localStorage.getItem(ADMIN_PROFILE_KEY);
    return raw ? JSON.parse(raw) : null;
  } catch (error) {
    return null;
  }
}

function normalizeAdminUser(user, index = 0) {
  if (!user) return null;
  const normalized = {
    id: user.id || `admin-${index + 1}`,
    name: user.name || user.username || 'Administrador',
    username: user.username || 'admin',
    passwordHash: user.passwordHash || '',
    role: user.role || 'owner',
    department: user.department || 'direccion',
    phone: user.phone || '',
    email: user.email || '',
    active: user.active !== false,
    createdAt: user.createdAt || new Date().toISOString(),
  };
  normalized.permissions = normalizePermissions({ ...user, role: normalized.role, department: normalized.department });
  return normalized;
}

function readAdminUsers() {
  try {
    const raw = localStorage.getItem(ADMIN_USERS_KEY);
    const users = raw ? JSON.parse(raw) : [];
    if (Array.isArray(users) && users.length) return users.map(normalizeAdminUser).filter(Boolean);

    const legacy = readAdminProfile();
    if (legacy) {
      const migrated = [normalizeAdminUser({
        ...legacy,
        id: 'owner-local',
        name: legacy.name || 'Administrador principal',
        role: 'owner',
        department: 'direccion',
        active: true,
      })];
      localStorage.setItem(ADMIN_USERS_KEY, JSON.stringify(migrated));
      return migrated;
    }
    return [];
  } catch (error) {
    return [];
  }
}

function writeAdminUsers(users) {
  localStorage.setItem(ADMIN_USERS_KEY, JSON.stringify(users.map(normalizeAdminUser).filter(Boolean)));
  window.dispatchEvent(new CustomEvent('lelusa-admin-users-change'));
}

function findAdminUser(username) {
  const wanted = String(username || '').trim().toLowerCase();
  return readAdminUsers().find(user => String(user.username || '').toLowerCase() === wanted) || null;
}

function readAdminSession() {
  try {
    const users = readAdminUsers();
    const raw = localStorage.getItem(ADMIN_SESSION_KEY);
    const session = raw ? JSON.parse(raw) : null;
    const user = users.find(item => item.username === session?.username && item.active !== false);
    if (!user || !session || Number(session.expiresAt || 0) <= Date.now()) {
      localStorage.removeItem(ADMIN_SESSION_KEY);
      return null;
    }
    return { ...session, userId: user.id, role: user.role, department: user.department, name: user.name, permissions: user.permissions || [] };
  } catch (error) {
    localStorage.removeItem(ADMIN_SESSION_KEY);
    return null;
  }
}

async function createAdminUser(payload) {
  const users = readAdminUsers();
  const username = String(payload.username || '').trim();
  const password = String(payload.password || '');
  if (!username || !password) throw new Error('Ingresa usuario y contraseña.');
  if (password.length < 8) throw new Error('La contraseña debe tener al menos 8 caracteres.');
  if (users.some(user => user.username.toLowerCase() === username.toLowerCase())) {
    throw new Error('Ese usuario ya existe.');
  }
  const user = normalizeAdminUser({
    id: `user-${Date.now()}`,
    name: payload.name || username,
    username,
    passwordHash: await hashAdminPassword(password),
    role: payload.role || 'staff',
    department: payload.department || 'decoracion',
    phone: payload.phone || '',
    email: payload.email || '',
    permissions: Array.isArray(payload.permissions) ? payload.permissions : getDefaultPermissions(payload.role || 'staff', payload.department || 'decoracion'),
    active: payload.active !== false,
    createdAt: new Date().toISOString(),
  }, users.length);
  writeAdminUsers([user, ...users]);
  return user;
}

function updateAdminUser(id, patch) {
  let updated = null;
  const users = readAdminUsers().map(user => {
    if (user.id !== id) return user;
    updated = normalizeAdminUser({ ...user, ...patch });
    return updated;
  });
  writeAdminUsers(users);
  return updated;
}

window.LelusaAdminAuth = {
  readUsers: readAdminUsers,
  createUser: createAdminUser,
  updateUser: updateAdminUser,
};

function AdminLoginField({ label, children }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
      <label style={{ fontSize: '12px', fontWeight: 700, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{label}</label>
      {children}
    </div>
  );
}

function AdminLoginPage({ targetPage, targetData, onLogin, onBack }) {
  const [users, setUsers] = React.useState(() => readAdminUsers());
  const [form, setForm] = React.useState({
    username: users[0]?.username || 'admin',
    password: '',
    confirm: '',
  });
  const [error, setError] = React.useState('');
  const [saving, setSaving] = React.useState(false);
  const setupMode = users.length === 0;

  const set = (key, value) => {
    setForm(current => ({ ...current, [key]: value }));
    setError('');
  };

  const submit = async (event) => {
    event.preventDefault();
    const username = form.username.trim();
    const password = form.password;

    if (!username || !password) {
      setError('Ingresa usuario y contraseña.');
      return;
    }
    if (setupMode && password.length < 8) {
      setError('La contraseña debe tener al menos 8 caracteres.');
      return;
    }
    if (setupMode && password !== form.confirm) {
      setError('Las contraseñas no coinciden.');
      return;
    }

    setSaving(true);
    try {
      const passwordHash = await hashAdminPassword(password);
      let activeProfile = null;

      if (setupMode) {
        activeProfile = normalizeAdminUser({
          id: 'owner-local',
          name: 'Administrador principal',
          username,
          passwordHash,
          role: 'owner',
          department: 'direccion',
          permissions: ALL_ADMIN_PERMISSIONS,
          active: true,
          createdAt: new Date().toISOString(),
        });
        writeAdminUsers([activeProfile]);
        localStorage.setItem(ADMIN_PROFILE_KEY, JSON.stringify(activeProfile));
        setUsers([activeProfile]);
      } else {
        activeProfile = findAdminUser(username);
      }

      if (!activeProfile || activeProfile.active === false || passwordHash !== activeProfile.passwordHash) {
        setError('Usuario o contraseña incorrectos.');
        setSaving(false);
        return;
      }

      localStorage.setItem(ADMIN_SESSION_KEY, JSON.stringify({
        username: activeProfile.username,
        userId: activeProfile.id,
        role: activeProfile.role,
        department: activeProfile.department,
        permissions: activeProfile.permissions || [],
        name: activeProfile.name,
        expiresAt: Date.now() + ADMIN_SESSION_TTL_MS,
      }));
      onLogin(targetPage, targetData);
    } catch (error) {
      setError('No se pudo iniciar sesión en este navegador.');
    } finally {
      setSaving(false);
    }
  };

  const inputStyle = {
    width: '100%',
    padding: '12px 14px',
    borderRadius: '12px',
    border: '1.5px solid var(--border)',
    background: 'var(--card)',
    color: 'var(--text)',
    fontFamily: "'DM Sans', sans-serif",
    fontSize: '14px',
    outline: 'none',
    boxSizing: 'border-box',
  };

  return (
    <div style={{ minHeight: '100vh', background: 'var(--bg-soft)', display: 'grid', placeItems: 'center', padding: '24px' }}>
      <div style={{ width: '100%', maxWidth: '420px', background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', padding: '28px', boxShadow: '0 18px 60px rgba(58,42,32,0.12)' }}>
        <Badge>{setupMode ? 'Crear acceso admin' : 'Acceso admin'}</Badge>
        <h1 style={{ margin: '14px 0 8px', fontFamily: "'Cormorant Garamond', serif", fontSize: '32px', color: 'var(--text)', lineHeight: 1.1 }}>
          {setupMode ? 'Configura tu cuenta' : 'Inicia sesión'}
        </h1>
        <p style={{ margin: '0 0 22px', fontSize: '13px', color: 'var(--muted)', lineHeight: 1.6 }}>
          {setupMode
            ? 'Esta cuenta se guarda en este navegador para proteger el panel de administración local.'
            : 'Tu sesión queda guardada por 12 horas en este navegador.'}
        </p>
        <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: '14px' }}>
          <AdminLoginField label="Usuario">
            <input value={form.username} onChange={event => set('username', event.target.value)} autoComplete="username" style={inputStyle} />
          </AdminLoginField>
          <AdminLoginField label="Contraseña">
            <input type="password" value={form.password} onChange={event => set('password', event.target.value)} autoComplete={setupMode ? 'new-password' : 'current-password'} style={inputStyle} />
          </AdminLoginField>
          {setupMode && (
            <AdminLoginField label="Confirmar contraseña">
              <input type="password" value={form.confirm} onChange={event => set('confirm', event.target.value)} autoComplete="new-password" style={inputStyle} />
            </AdminLoginField>
          )}
          {error && <div style={{ padding: '11px 12px', borderRadius: '12px', background: '#FFE0E0', color: '#B83232', fontSize: '13px' }}>{error}</div>}
          <Btn type="submit" disabled={saving} style={{ justifyContent: 'center', marginTop: '4px' }}>
            {saving ? 'Validando...' : (setupMode ? 'Crear acceso' : 'Entrar al panel')}
          </Btn>
          <Btn type="button" variant="ghost" onClick={onBack} style={{ justifyContent: 'center' }}>
            Volver al sitio
          </Btn>
        </form>
      </div>
    </div>
  );
}

function AdminAccessDeniedPage() {
  const { navigate, adminUser, logoutAdmin } = React.useContext(window.AppContext);
  return (
    <AdminLayout title="Acceso limitado" subtitle={adminUser ? `${adminUser.name || adminUser.username} · ${adminUser.department || 'sin departamento'}` : ''}>
      <div style={{ maxWidth: 560, margin: '32px auto', background: 'var(--card)', border: '1px solid var(--border)', borderRadius: 20, padding: 24, textAlign: 'center', boxShadow: '0 12px 36px rgba(58,42,32,0.06)' }}>
        <div style={{ width: 52, height: 52, borderRadius: 16, background: '#FFF3DC', display: 'grid', placeItems: 'center', margin: '0 auto 14px' }}>
          <Icon name="settings" size={22} color="#C8881A" />
        </div>
        <h2 style={{ margin: '0 0 8px', fontFamily: "'Cormorant Garamond', serif", fontSize: 28, color: 'var(--text)' }}>No tienes permiso para esta sección</h2>
        <p style={{ margin: '0 0 18px', color: 'var(--muted)', fontSize: 13, lineHeight: 1.6 }}>
          Un administrador puede cambiar tus accesos desde Equipo.
        </p>
        <div style={{ display: 'flex', justifyContent: 'center', gap: 10, flexWrap: 'wrap' }}>
          <Btn onClick={() => navigate('admin-dashboard')}>Ir al dashboard</Btn>
          <Btn variant="ghost" onClick={logoutAdmin}>Cerrar sesión</Btn>
        </div>
      </div>
    </AdminLayout>
  );
}

// Wrapper nombrado para la página de email (lee window.AdminEmailPage en
// tiempo de render). Definido a nivel de módulo para tener identidad estable.
function AdminEmailPageSlot() {
  const EmailPage = window.AdminEmailPage;
  if (typeof EmailPage === 'function') return <EmailPage />;
  return (
    <AdminLayout title="Email" subtitle="Modulo no disponible">
      <div style={{ maxWidth: 620, background: 'var(--card)', border: '1px solid var(--border)', borderRadius: 18, padding: 22, color: 'var(--muted)', fontSize: 13 }}>
        No se pudo cargar el modulo de email. Recarga la pagina para obtener los archivos actualizados.
      </div>
    </AdminLayout>
  );
}

// pageMap a nivel de MÓDULO: los componentes mantienen identidad estable
// entre renders de App. Definirlo dentro de App recreaba cada componente
// en cada render, remontando la página y robando el foco a los inputs.
const PAGE_MAP = {
  home:            () => <><NavBar /><HomePage /><Footer /></>,
  catalog:         () => <CatalogPage />,
  'deco-detail':   () => <DecoDetailPage />,
  customizer:      () => <CustomizerPage />,
  'quote-form':    () => <QuoteFormPage />,
  'admin-dashboard': () => <DashboardPage />,
  'admin-quotes':    () => <QuotesPage />,
  'admin-designs':   () => <DesignsPage />,
  'admin-desserts':  () => <DessertsPage />,
  'admin-team':      () => <TeamPage />,
  'admin-calendar':  () => <CalendarPage />,
  'admin-event-detail': () => <EventDetailPage />,
  'admin-email':     () => <AdminEmailPageSlot />,
  'admin-finance':   () => <FinancePage />,
  'admin-inventory': () => <InventoryPage />,
  'admin-postera': () => <AdminPosteraPage />,
  'admin-settings':  () => <SettingsPage />,
  'admin-scene-editor': () => <AdminSceneEditorPage />,
  'admin-send-notification': () => <SendNotificationPage />,
};

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const initialRoute = React.useMemo(() => getRouteFromLocation(), []);
  const [currentPage, setCurrentPage] = React.useState(initialRoute.page);
  const [pageData, setPageData] = React.useState(initialRoute.data);
  const [adminSession, setAdminSession] = React.useState(() => readAdminSession());
  const [transitionDir, setTransitionDir] = React.useState('tab');

  React.useEffect(() => { applyTheme(t.theme); }, [t.theme]);

  React.useEffect(() => {
    const r = document.documentElement;
    const radii = {
      soft:  { card: '24px', input: '12px' },
      round: { card: '36px', input: '20px' },
      sharp: { card: '12px', input: '8px' },
    };
    const rad = radii[t.roundness] || radii.soft;
    r.style.setProperty('--radius-card', rad.card);
    r.style.setProperty('--radius-input', rad.input);
  }, [t.roundness]);

  window.LelusaGestures.useEdgeSwipeBack({ enabled: true });

  React.useEffect(() => {
    const url = getUrlForPage(currentPage, pageData);
    const currentUrl = normalizeUrlPath(window.location.href);

    if (normalizeUrlPath(url) !== currentUrl) {
      window.history.replaceState({ page: currentPage, pageData }, '', url);
    } else {
      window.history.replaceState({ page: currentPage, pageData }, '', currentUrl);
    }

    const handlePopState = event => {
      const route = event.state?.page
        ? { page: event.state.page, data: event.state.pageData || {} }
        : getRouteFromLocation();

      setTransitionDir('back');
      setCurrentPage(route.page);
      setPageData(route.data);
      // scroll handled by PageTransition
    };

    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, []);

  const navigate = React.useCallback((page, data = {}, hint = null) => {
    const url = getUrlForPage(page, data);
    setCurrentPage(prev => {
      const dir = String(page).startsWith('admin-')
        ? 'tab'
        : (window.resolveDirection ? window.resolveDirection(prev, page, hint) : 'tab');
      setTransitionDir(dir);
      return page;
    });
    window.history.pushState({ page, pageData: data }, '', url);
    setPageData(data);
    // scroll handled by PageTransition (and the desktop/reduced plain path)
  }, []);

  const completeAdminLogin = React.useCallback((page, data = {}) => {
    const session = readAdminSession();
    setAdminSession(session);
    const nextPage = page || 'admin-dashboard';
    const nextData = data || {};
    const url = getUrlForPage(nextPage, nextData);
    window.history.replaceState({ page: nextPage, pageData: nextData }, '', url);
    setCurrentPage(nextPage);
    setPageData(nextData);
    window.scrollTo({ top: 0, behavior: 'instant' });
  }, []);

  const logoutAdmin = React.useCallback(() => {
    localStorage.removeItem(ADMIN_SESSION_KEY);
    setAdminSession(null);
    navigate('home');
  }, [navigate]);

  const ctxValue = React.useMemo(
    () => ({ navigate, currentPage, pageData, adminUser: adminSession }),
    [navigate, currentPage, pageData, adminSession]
  );

  const PageComponent = PAGE_MAP[currentPage] || PAGE_MAP.home;
  const shouldGateAdmin = isAdminPage(currentPage) && !adminSession;
  const shouldBlockAdmin = isAdminPage(currentPage) && adminSession && !canAccessAdminPage(adminSession, currentPage);

  return (
    <window.AppContext.Provider value={{ ...ctxValue, adminSession, logoutAdmin }}>
      {shouldGateAdmin ? (
        <AdminLoginPage
          targetPage={currentPage}
          targetData={pageData}
          onLogin={completeAdminLogin}
          onBack={() => navigate('home')}
        />
      ) : shouldBlockAdmin ? (
        <AdminAccessDeniedPage />
      ) : (
        <PageTransition pageKey={currentPage} direction={transitionDir}>
          <PageComponent />
        </PageTransition>
      )}

      {!shouldGateAdmin && !isAdminPage(currentPage) && <BottomNav />}
      {!shouldGateAdmin && isAdminPage(currentPage) && currentPage !== 'admin-scene-editor' && currentPage !== 'admin-postera' && <AdminBottomNav />}
      <TweaksPanel>
        <TweakSection label="Tema visual" />
        <TweakRadio
          label="Paleta de colores"
          value={t.theme}
          options={['floral', 'boho', 'luxury']}
          labels={['Floral', 'Boho', 'Luxury']}
          onChange={v => setTweak('theme', v)}
        />
        <TweakRadio
          label="Esquinas"
          value={t.roundness}
          options={['soft', 'round', 'sharp']}
          labels={['Suaves', 'Redondas', 'Rectas']}
          onChange={v => setTweak('roundness', v)}
        />

        <TweakSection label="Navegar a..." />
        <TweakButton label="Inicio" onClick={() => navigate('home')} />
        <TweakButton label="Catalogo" onClick={() => navigate('catalog')} />
        <TweakButton label="Detalle: Baby Shower Boho" onClick={() => navigate('deco-detail', { decoId: 1 })} />
        <TweakButton label="Personalizar decoracion" onClick={() => navigate('customizer', { decoId: 1 })} />
        <TweakButton label="Formulario de cotizacion" onClick={() => navigate('quote-form', { decoId: 1, total: 750, extras: ['letras'] })} />
      </TweaksPanel>
    </window.AppContext.Provider>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
