// App shell: sidebar nav for desktop. On mobile (≤1024px) the entire
// .app-sidebar element is hidden via CSS — mobile uses the bottom tab bar
// + bottom sheet pattern instead (see BottomTabBar / MoreSheet below).
function Sidebar({ page, onPage }) {
  const { setCmdOpen } = useApp();
  const isAdmin = window.APP_USER?.is_admin;
  const items1 = [
    { id: 'dashboard', icon: '◉', label: 'סקירה', shortcut: 'G D' },
    { id: 'txns',      icon: '≡', label: 'עסקאות', count: D.current?.txns?.length || 0, shortcut: 'G T' },
    { id: 'trends',    icon: '⌃', label: 'מגמות', shortcut: 'G R' },
    { id: 'ai',        icon: '✦', label: 'דוח Cai', shortcut: 'G A' },
    { id: 'savings',   icon: '↓', label: 'איפה לחסוך', count: D.savings?.items?.length || 0, shortcut: 'G S' },
  ];
  const items2 = [
    { id: 'budgets', icon: '◐', label: 'תקציבים' },
    { id: 'subs',    icon: '↻', label: 'מנויים', count: D.subscriptions?.length || 0 },
    { id: 'goals',   icon: '★', label: 'יעדים' },
    { id: 'settings', icon: '⚙', label: 'הגדרות' },
  ];
  if (isAdmin) {
    items2.push({ id: 'admin', icon: '⚒', label: 'ניהול' });
  }
  return (
    <aside className="app-sidebar">
      <div style={{ padding: '0 8px', display: 'flex', alignItems: 'center', gap: 9 }}>
        <img src="static/app/logo.png" alt="CliBank" style={{
          width: 28, height: 28, borderRadius: 8, objectFit: 'cover',
          boxShadow: '0 2px 6px rgba(0,0,0,.08)',
        }} />
        <span style={{ fontSize: 15, fontWeight: 600, letterSpacing: '-0.015em' }}>CliBank</span>
      </div>

      <div onClick={() => setCmdOpen(true)} style={{
        display: 'flex', alignItems: 'center', gap: 8, padding: '7px 10px',
        background: 'var(--surface)', borderRadius: 10, cursor: 'pointer',
        boxShadow: 'var(--shadow-sm)', fontSize: 12.5, color: 'var(--ink-soft)',
      }}>
        <span style={{ fontSize: 12 }}>⌕</span>
        <span style={{ flex: 1 }}>חיפוש</span>
        <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', background: 'var(--bg-deep)', padding: '1px 6px', borderRadius: 4 }}>⌘K</span>
      </div>

      <NavGroup label="כללי" items={items1} active={page} onSelect={onPage} />
      <NavGroup label="ניהול" items={items2} active={page} onSelect={onPage} />

      <div style={{ marginTop: 'auto', display: 'flex', flexDirection: 'column', gap: 12, padding: '0 4px' }}>
        <ThemeToggle />
        <UserCard />
      </div>
    </aside>
  );
}

function UserCard() {
  const { setPage } = useApp();
  const u = window.APP_USER || {};
  const initial = (u.name || u.email || '?').trim()[0].toUpperCase();
  const accountCount = (D.accounts || []).length;
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  // Close dropdown when clicking outside
  useEffect(() => {
    if (!open) return;
    const onClick = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener('mousedown', onClick);
    return () => document.removeEventListener('mousedown', onClick);
  }, [open]);

  const goTo = (pageId) => { setPage(pageId); setOpen(false); };
  const logout = async () => {
    setOpen(false);
    if (!confirm('להתנתק מהחשבון?')) return;
    if (window.APP_LOGOUT) await window.APP_LOGOUT();
    else window.location.href = '/login';
  };

  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <div
        onClick={() => setOpen(o => !o)}
        style={{
          display: 'flex', alignItems: 'center', gap: 9,
          padding: '8px 6px', borderTop: '0.5px solid var(--rule)', paddingTop: 12,
          cursor: 'pointer',
          transition: 'background .14s', borderRadius: 8,
          background: open ? 'var(--surface)' : 'transparent',
        }}
        title="לחץ לתפריט"
      >
        <div style={{
          width: 28, height: 28, borderRadius: '50%', background: 'var(--ink)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 12, fontWeight: 600, color: 'var(--bg)',
        }}>{initial}</div>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontSize: 12, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {u.name || 'משתמש'}
          </div>
          <div style={{ fontSize: 10.5, color: 'var(--ink-soft)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {accountCount} חשבונות
          </div>
        </div>
        <span style={{ color: 'var(--ink-soft)', fontSize: 10, transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .15s' }}>▴</span>
      </div>

      {open && (
        <div className="fade-in" style={{
          position: 'absolute', bottom: '100%', insetInlineStart: 0,
          width: 220, background: 'var(--surface)',
          borderRadius: 12, boxShadow: 'var(--shadow-lg)',
          padding: 6, marginBottom: 6, zIndex: 50,
          border: '0.5px solid var(--rule)',
        }}>
          {/* Header */}
          <div style={{ padding: '8px 10px 6px', borderBottom: '0.5px solid var(--rule)', marginBottom: 4 }}>
            <div style={{ fontSize: 12.5, fontWeight: 600 }}>{u.name}</div>
            <div style={{ fontSize: 10.5, color: 'var(--ink-soft)', fontFamily: 'var(--font-mono)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
              {u.email}
            </div>
          </div>
          <MenuItem icon="◷" label="החשבון שלי" onClick={() => goTo('profile')} />
          {u.is_admin && <MenuItem icon="⚒" label="ניהול משתמשים" onClick={() => goTo('admin')} />}
          <MenuItem icon="⚙" label="הגדרות" onClick={() => goTo('settings')} />
          <div style={{ height: 0.5, background: 'var(--rule)', margin: '4px 0' }} />
          <MenuItem icon="↪" label="החלף משתמש" onClick={logout} sub="התנתק וחזור למסך התחברות" />
          <MenuItem icon="⏻" label="התנתק" onClick={logout} alert />
        </div>
      )}
    </div>
  );
}

function MenuItem({ icon, label, onClick, alert, sub }) {
  return (
    <div onClick={onClick} style={{
      padding: '8px 10px', borderRadius: 7, cursor: 'pointer',
      display: 'flex', alignItems: 'center', gap: 9,
      transition: 'background .12s',
      color: alert ? 'var(--alert)' : 'var(--ink)',
    }}
      onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-deep)'}
      onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
    >
      <span style={{ width: 14, color: alert ? 'var(--alert)' : 'var(--ink-soft)', fontSize: 12, textAlign: 'center' }}>{icon}</span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 12.5, fontWeight: 500 }}>{label}</div>
        {sub && <div style={{ fontSize: 10, color: 'var(--ink-soft)', marginTop: 1 }}>{sub}</div>}
      </div>
    </div>
  );
}

function NavGroup({ label, items, active, onSelect }) {
  return (
    <div>
      <div style={{ fontSize: 10.5, fontWeight: 600, color: 'var(--ink-soft)', letterSpacing: '0.05em', textTransform: 'uppercase', padding: '0 10px', marginBottom: 6 }}>{label}</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
        {items.map(it => {
          const on = it.id === active;
          return (
            <div key={it.id} onClick={() => onSelect(it.id)} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '7px 10px', borderRadius: 8, cursor: 'pointer',
              background: on ? 'var(--surface)' : 'transparent',
              boxShadow: on ? 'var(--shadow-sm)' : 'none',
              fontSize: 13, fontWeight: on ? 600 : 500,
              color: on ? 'var(--ink)' : 'var(--ink-2)',
              transition: 'background .14s',
            }}>
              <span style={{ width: 16, color: on ? 'var(--accent)' : 'var(--ink-soft)', fontSize: 12, textAlign: 'center' }}>{it.icon}</span>
              <span style={{ flex: 1 }}>{it.label}</span>
              {it.count != null && (
                <span className="tnum" style={{ fontSize: 10.5, color: 'var(--ink-soft)', fontFamily: 'var(--font-mono)' }}>{it.count}</span>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function ThemeToggle() {
  const { theme, setTheme } = useApp();
  return (
    <div style={{
      display: 'flex', background: 'var(--surface)', borderRadius: 10,
      padding: 2, boxShadow: 'var(--shadow-sm)', fontSize: 11,
    }}>
      {[['light','☀','בהיר'],['dark','☾','כהה']].map(([k, ic, l]) => (
        <button key={k} onClick={() => setTheme(k)} style={{
          flex: 1, padding: '6px 8px', border: 'none', cursor: 'pointer',
          background: theme === k ? 'var(--bg-deep)' : 'transparent',
          color: theme === k ? 'var(--ink)' : 'var(--ink-soft)',
          borderRadius: 8, fontSize: 11, fontWeight: 500,
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
        }}>
          <span>{ic}</span>{l}
        </button>
      ))}
    </div>
  );
}

// Command Palette
function CommandPalette() {
  const { cmdOpen, setCmdOpen, setPage } = useApp();
  const [q, setQ] = useState('');
  const [idx, setIdx] = useState(0);
  const inputRef = useRef();
  useEffect(() => { if (cmdOpen) setTimeout(() => inputRef.current?.focus(), 30); else { setQ(''); setIdx(0); } }, [cmdOpen]);

  const allItems = useMemo(() => [
    { type: 'page', id: 'dashboard', label: 'סקירה', sub: 'דשבורד ראשי', icon: '◉' },
    { type: 'page', id: 'txns', label: 'עסקאות', sub: 'כל החיובים', icon: '≡' },
    { type: 'page', id: 'trends', label: 'מגמות', sub: 'השוואת חודשים', icon: '⌃' },
    { type: 'page', id: 'ai', label: 'דוח Cai', sub: 'תובנות חודשיות', icon: '✦' },
    { type: 'page', id: 'savings', label: 'איפה לחסוך', sub: 'המלצות חיסכון מבוססות נתונים', icon: '↓' },
    { type: 'page', id: 'budgets', label: 'תקציבים', icon: '◐' },
    { type: 'page', id: 'subs', label: 'מנויים', icon: '↻' },
    { type: 'page', id: 'goals', label: 'יעדים', icon: '★' },
    { type: 'page', id: 'settings', label: 'הגדרות', icon: '⚙' },
    ...D.current.txns.slice(0, 30).map(t => ({
      type: 'txn', id: t.id, label: t.description,
      sub: `${fmtDate(t.date)} · ${t.category} · ${fmtILS(t.amount)}`, icon: D.categories[t.category]?.icon || '·',
    })),
  ], []);

  const filtered = useMemo(() => {
    if (!q) return allItems.slice(0, 8);
    const lq = q.toLowerCase();
    return allItems.filter(i => i.label.toLowerCase().includes(lq) || (i.sub||'').toLowerCase().includes(lq)).slice(0, 12);
  }, [q, allItems]);

  useEffect(() => { setIdx(0); }, [q]);
  useEffect(() => {
    if (!cmdOpen) return;
    const onKey = (e) => {
      if (e.key === 'Escape') setCmdOpen(false);
      if (e.key === 'ArrowDown') { e.preventDefault(); setIdx(i => Math.min(filtered.length-1, i+1)); }
      if (e.key === 'ArrowUp')   { e.preventDefault(); setIdx(i => Math.max(0, i-1)); }
      if (e.key === 'Enter') {
        const it = filtered[idx];
        if (it?.type === 'page') { setPage(it.id); setCmdOpen(false); }
        else if (it?.type === 'txn') { setCmdOpen(false); setPage('txns'); }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [cmdOpen, filtered, idx]);

  if (!cmdOpen) return null;
  return (
    <div onClick={() => setCmdOpen(false)} style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', backdropFilter: 'blur(8px)',
      zIndex: 100, display: 'flex', justifyContent: 'center', alignItems: 'flex-start', paddingTop: '12vh',
      animation: 'fade-in .15s',
    }}>
      <div onClick={e => e.stopPropagation()} className="slide-up" style={{
        width: 540, maxWidth: '90%', background: 'var(--surface)', borderRadius: 16,
        boxShadow: 'var(--shadow-lg)', overflow: 'hidden',
      }}>
        <div style={{ padding: '14px 18px', borderBottom: '0.5px solid var(--rule)', display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 14, color: 'var(--ink-soft)' }}>⌕</span>
          <input ref={inputRef} value={q} onChange={e => setQ(e.target.value)}
                 placeholder="חפש עסקאות, עמודים, פעולות…"
                 style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', fontSize: 14 }} />
          <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-soft)', background: 'var(--bg-deep)', padding: '2px 7px', borderRadius: 4 }}>ESC</span>
        </div>
        <div className="thin-scroll" style={{ maxHeight: 400, overflowY: 'auto', padding: 6 }}>
          {filtered.length === 0 && (
            <div style={{ padding: '40px 20px', textAlign: 'center', color: 'var(--ink-soft)', fontSize: 13 }}>אין תוצאות</div>
          )}
          {filtered.map((it, i) => (
            <div key={`${it.type}-${it.id}`}
                 onMouseEnter={() => setIdx(i)}
                 onClick={() => { if (it.type === 'page') { setPage(it.id); setCmdOpen(false); } }}
                 style={{
              display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px',
              borderRadius: 8, cursor: 'pointer',
              background: i === idx ? 'var(--bg-deep)' : 'transparent',
            }}>
              <span style={{ width: 28, height: 28, borderRadius: 8, background: 'var(--bg-deep)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13 }}>{it.icon}</span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 500 }}>{it.label}</div>
                {it.sub && <div style={{ fontSize: 11, color: 'var(--ink-soft)' }}>{it.sub}</div>}
              </div>
              <span style={{ fontSize: 10.5, color: 'var(--ink-soft)', textTransform: 'uppercase' }}>{it.type === 'page' ? 'עמוד' : 'עסקה'}</span>
            </div>
          ))}
        </div>
        <div style={{ padding: '8px 14px', borderTop: '0.5px solid var(--rule)', fontSize: 10.5, color: 'var(--ink-soft)', display: 'flex', gap: 14, fontFamily: 'var(--font-mono)' }}>
          <span>↑↓ ניווט</span><span>↵ בחירה</span><span>ESC סגירה</span>
        </div>
      </div>
    </div>
  );
}

// ─── Mobile chrome (iOS Human-Interface-style) ───────────────────────
//
// Pattern:
//   • Sticky glass top bar with the page title + a single trailing
//     action (search). No hamburger — primary nav lives in the bottom
//     tab bar instead.
//   • Bottom tab bar with the 5 most-used destinations.
//   • A "More" tab opens a bottom-sheet listing the rest, the user
//     account, and Logout.
//
// All CSS lives in styles.css (mobile @media query). These components
// just render the structure and toggle classes.

const PAGE_LABELS = {
  dashboard: 'סקירה', txns: 'עסקאות', trends: 'מגמות', ai: 'דוח Cai',
  savings: 'איפה לחסוך', budgets: 'תקציבים', subs: 'מנויים', goals: 'יעדים',
  settings: 'הגדרות', profile: 'החשבון שלי', admin: 'ניהול',
};

// Primary nav for the bottom tab bar — pick the 5 most-used destinations.
// Order matters (RTL means rightmost is first).
function getPrimaryTabs() {
  return [
    { id: 'dashboard', icon: '◉', label: 'סקירה' },
    { id: 'txns',      icon: '≡', label: 'עסקאות' },
    { id: 'ai',        icon: '✦', label: 'Cai' },
    { id: 'subs',      icon: '↻', label: 'מנויים', count: D.subscriptions?.length || 0 },
    { id: '__more',    icon: '⋯', label: 'עוד' },
  ];
}

function MobileTopbar({ page, onSearch }) {
  return (
    <header className="mobile-topbar" role="banner">
      <div className="mobile-topbar-title">{PAGE_LABELS[page] || 'CliBank'}</div>
      <button
        className="topbar-action"
        onClick={onSearch}
        aria-label="חיפוש"
      >⌕</button>
    </header>
  );
}

function BottomTabBar({ page, onPick }) {
  const tabs = getPrimaryTabs();
  return (
    <nav className="tab-bar" role="navigation" aria-label="ניווט ראשי">
      {tabs.map(t => {
        const active = page === t.id;
        return (
          <button
            key={t.id}
            className={`tab-item ${active ? 'active' : ''}`}
            onClick={() => onPick(t.id)}
            aria-label={t.label}
            aria-current={active ? 'page' : undefined}
          >
            <span className="tab-item-icon">{t.icon}</span>
            <span>{t.label}</span>
            {t.count > 0 && <span className="tab-item-badge">{t.count > 99 ? '99+' : t.count}</span>}
          </button>
        );
      })}
    </nav>
  );
}

// Bottom sheet for "More" destinations + account + logout.
function MoreSheet({ open, onClose, onPick, page }) {
  const isAdmin = window.APP_USER?.is_admin;
  const u = window.APP_USER || {};

  // Click backdrop = close
  const onBackdrop = (e) => {
    if (e.target === e.currentTarget) onClose();
  };

  // Lock body scroll when sheet open
  useEffect(() => {
    if (!open) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, [open]);

  const items = [
    { id: 'trends',   icon: '⌃', label: 'מגמות' },
    { id: 'savings',  icon: '↓', label: 'איפה לחסוך', count: D.savings?.items?.length || 0 },
    { id: 'budgets',  icon: '◐', label: 'תקציבים' },
    { id: 'goals',    icon: '★', label: 'יעדים' },
    { id: 'settings', icon: '⚙', label: 'הגדרות' },
  ];
  const accountItems = [
    { id: 'profile',  icon: '👤', label: 'החשבון שלי' },
  ];
  if (isAdmin) accountItems.push({ id: 'admin', icon: '⚒', label: 'ניהול' });

  const handlePick = (id) => { onPick(id); onClose(); };
  const handleLogout = async () => {
    onClose();
    if (!confirm('להתנתק מהחשבון?')) return;
    if (window.APP_LOGOUT) await window.APP_LOGOUT();
    else window.location.href = '/login';
  };

  return (
    <>
      <div
        className={`sheet-backdrop ${open ? 'open' : ''}`}
        onClick={onBackdrop}
        aria-hidden="true"
      />
      <div
        className={`sheet ${open ? 'open' : ''}`}
        role="dialog"
        aria-modal="true"
        aria-label="עוד"
      >
        <div className="sheet-handle" />

        {/* Account header */}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '8px 16px 18px', borderBottom: '0.5px solid var(--rule)', marginBottom: 8,
        }}>
          <div style={{
            width: 44, height: 44, borderRadius: 12,
            background: 'var(--ink)', color: 'var(--bg)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: 18, fontWeight: 700,
          }}>{(u.name || u.email || '?')[0].toUpperCase()}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 15, fontWeight: 600, color: 'var(--ink)' }}>{u.name || 'משתמש'}</div>
            <div style={{ fontSize: 12, color: 'var(--ink-soft)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{u.email}</div>
          </div>
          {u.is_admin && (
            <span style={{
              fontSize: 10, padding: '3px 8px', borderRadius: 5,
              background: 'rgba(10,132,255,0.12)', color: 'var(--accent)', fontWeight: 600,
            }}>אדמין</span>
          )}
        </div>

        <div className="sheet-title">ניווט</div>
        {items.map(it => (
          <button key={it.id} className="sheet-item" onClick={() => handlePick(it.id)}>
            <span className="sheet-item-icon">{it.icon}</span>
            <span className="sheet-item-label">{it.label}</span>
            {it.count > 0 && <span className="sheet-item-count">{it.count}</span>}
          </button>
        ))}

        <div className="sheet-title" style={{ marginTop: 8 }}>חשבון</div>
        {accountItems.map(it => (
          <button key={it.id} className="sheet-item" onClick={() => handlePick(it.id)}>
            <span className="sheet-item-icon">{it.icon}</span>
            <span className="sheet-item-label">{it.label}</span>
          </button>
        ))}
        <button className="sheet-item danger" onClick={handleLogout}>
          <span className="sheet-item-icon">⤴</span>
          <span className="sheet-item-label">התנתק</span>
        </button>
      </div>
    </>
  );
}

window.Sidebar = Sidebar;
window.CommandPalette = CommandPalette;
window.MobileTopbar = MobileTopbar;
window.BottomTabBar = BottomTabBar;
window.MoreSheet = MoreSheet;
