// screens-extras.jsx — Rental flow, swipe browse, portfolio, notifications, profile, admin

// ─── MIETEN DASHBOARD ──────────────────────────────────────────────────
function MietenDashboardScreen({ ctx }) {
  const { listings, searches, navigate, user } = ctx;
  const rentalSearches = searches.filter(s => s.category === 'miete');
  const newRentals = listings.filter(l => l.type === 'miete').slice(0, 3);

  return (
    <div className="phone-scroll fade-in" style={{ paddingBottom: 100, background: 'var(--bg)' }}>
      <div style={{ padding: '60px 20px 0' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <div>
            <div style={{ fontSize: 13, color: 'var(--ink-muted)', fontWeight: 500 }}>
              {((h => h < 11 ? 'Guten Morgen' : h < 17 ? 'Guten Tag' : 'Guten Abend')(new Date().getHours()))}, {(user?.name || user?.email || 'Chris').trim().split(/\s+/)[0] || 'Chris'} · Mieten
            </div>
            <h1 style={{ margin: '6px 0 0', fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 38, lineHeight: 1.0, letterSpacing: -0.025 }}>
              Mietwohnungen
            </h1>
          </div>
          <IconBtn onClick={() => navigate('searchBuilderMiete')}><I.plus style={{ width: 22, height: 22, strokeWidth: 2.4 }} /></IconBtn>
        </div>
      </div>

      <div style={{ padding: '16px 16px 0' }}>
        <TokenBanner ctx={ctx} />
      </div>

      <div style={{ padding: '20px 16px 0', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <StatTile value={rentalSearches.filter(s => s.active).length} label="Aktive Suchen" />
        <StatTile value={rentalSearches.reduce((s,x) => s+x.matches, 0)} label="Treffer" />
        <StatTile value={`+${rentalSearches.reduce((s,x) => s+x.newToday, 0)}`} label="Neu heute" accent />
        <StatTile value="Ø 17 Tg." label="Time-to-rent" delta="lokaler Schnitt" />
      </div>

      <Section title="Ihre Mietsuchen" trailing="+ Neue">
        {rentalSearches.length === 0 ? (
          <EmptyState
            icon={<I.key />}
            title="Noch keine Mietsuche"
            subtitle="Legen Sie Ihre erste Suche an und wir benachrichtigen Sie bei neuen Inseraten."
            cta={<button onClick={() => navigate('searchBuilderMiete')} className="btn btn-accent">Mietsuche erstellen</button>}
          />
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {rentalSearches.map(s => (
              <SearchCard key={s.id} search={s} onTap={() => navigate('mietenResults', { searchId: s.id })} />
            ))}
          </div>
        )}
      </Section>

      <Section title="Neue Inserate" trailing="Alle ansehen" onTrailing={() => navigate('mietenResults', { searchId: rentalSearches[0]?.id })}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {newRentals.map(l => (
            <ListingRow key={l.id} listing={l} onTap={() => navigate('listing', { id: l.id })} />
          ))}
        </div>
      </Section>

      <Section title="Info">
        <div className="card" style={{ padding: 14, display: 'flex', gap: 12, alignItems: 'center' }}>
          <div style={{ width: 36, height: 36, borderRadius: 10, background: 'var(--info-soft)', color: 'var(--info)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <I.shield />
          </div>
          <div style={{ flex: 1, fontSize: 12, color: 'var(--ink-2)', lineHeight: 1.5 }}>
            Mietangebote werden <strong>nicht KI-bewertet</strong>. Sortierung nach Neuheit und Stichwortmatch.
          </div>
        </div>
      </Section>
    </div>
  );
}

function SearchCard({ search, onTap }) {
  return (
    <div className="card" onClick={onTap} style={{ padding: '14px 16px', cursor: 'pointer' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
        <div style={{ flex: 1 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
            <span style={{
              width: 8, height: 8, borderRadius: 999,
              background: search.active ? 'var(--success)' : 'var(--ink-faint)',
              boxShadow: search.active ? '0 0 0 3px rgba(47,143,90,.18)' : 'none',
            }} />
            <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--ink)', letterSpacing: -0.01 }}>{search.name}</div>
          </div>
          <div style={{ fontSize: 12, color: 'var(--ink-muted)' }}>
            {search.city} +{search.radius}km · {fmtPriceShort(search.priceMin)}–{fmtPriceShort(search.priceMax)} · {search.roomsMin}–{search.roomsMax} Zi.
          </div>
        </div>
        <I.chevR style={{ color: 'var(--ink-faint)' }} />
      </div>
      <div style={{ display: 'flex', gap: 6, marginTop: 12, alignItems: 'center', flexWrap: 'wrap' }}>
        <span className="chip" style={{ fontSize: 11 }}>
          <strong style={{ color: 'var(--ink)' }}>{search.matches}</strong>&nbsp;Treffer
        </span>
        {search.newToday > 0 && <span className="chip chip-accent" style={{ fontSize: 11 }}>+{search.newToday} neu</span>}
        {search.aiEnabled && <span className="chip chip-info" style={{ fontSize: 11 }}>KI</span>}
        <span style={{ fontSize: 11, color: 'var(--ink-faint)', marginLeft: 'auto' }}>
          {fmtRelative(search.lastRun)}
        </span>
      </div>
    </div>
  );
}

// ─── SWIPE BROWSE (Tinder-style) ───────────────────────────────────────
function SwipeScreen({ ctx }) {
  const { listings, back, navigate, favs, toggleFav, archiveListing, archived } = ctx;
  const queue = listings.filter(l => l.type === 'kauf' && !archived.has(l.id)).slice(0, 8);
  const [idx, setIdx] = React.useState(0);
  const [dragX, setDragX] = React.useState(0);
  const [dragging, setDragging] = React.useState(false);
  const startX = React.useRef(0);
  const currentY = React.useRef(0);

  const onStart = (e) => {
    startX.current = (e.touches ? e.touches[0].clientX : e.clientX);
    currentY.current = (e.touches ? e.touches[0].clientY : e.clientY);
    setDragging(true);
  };
  const onMove = (e) => {
    if (!dragging) return;
    const x = (e.touches ? e.touches[0].clientX : e.clientX);
    setDragX(x - startX.current);
  };
  const onEnd = () => {
    if (!dragging) return;
    setDragging(false);
    if (Math.abs(dragX) > 100) {
      const decision = dragX > 0 ? 'like' : 'pass';
      const item = queue[idx];
      if (decision === 'like') toggleFav(item.id, true);
      else archiveListing(item.id);
      setDragX(dragX > 0 ? 400 : -400);
      setTimeout(() => {
        setDragX(0);
        setIdx(i => i + 1);
      }, 180);
    } else {
      setDragX(0);
    }
  };

  const decide = (decision) => {
    const item = queue[idx];
    if (!item) return;
    if (decision === 'like') toggleFav(item.id, true);
    else archiveListing(item.id);
    setDragX(decision === 'like' ? 400 : -400);
    setTimeout(() => {
      setDragX(0);
      setIdx(i => i + 1);
    }, 180);
  };

  const current = queue[idx];
  const next = queue[idx + 1];
  const angle = dragX * 0.06;
  const likeOpacity = Math.max(0, Math.min(1, dragX / 80));
  const passOpacity = Math.max(0, Math.min(1, -dragX / 80));

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: '#1F1A14', color: '#fff' }}>
      <div style={{ padding: '60px 20px 12px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <button onClick={back} style={{ background: 'rgba(255,255,255,.1)', border: 0, color: '#fff', width: 40, height: 40, borderRadius: 999, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
          <I.chevL />
        </button>
        <div style={{ textAlign: 'center' }}>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 22, letterSpacing: -0.01 }}>Entdecken</div>
          <div style={{ fontSize: 11, color: 'rgba(255,255,255,.55)', marginTop: 2 }}>{Math.min(idx+1, queue.length)} / {queue.length}</div>
        </div>
        <div style={{ width: 40 }} />
      </div>

      <div style={{ flex: 1, position: 'relative', padding: '20px 20px 0' }}>
        {current ? (
          <>
            {/* Next card (peek behind) */}
            {next && (
              <SwipeCard
                listing={next}
                style={{
                  transform: 'scale(.94) translateY(20px)', opacity: .6, pointerEvents: 'none',
                }}
              />
            )}
            {/* Current card */}
            <SwipeCard
              listing={current}
              onStart={onStart} onMove={onMove} onEnd={onEnd}
              onTap={() => Math.abs(dragX) < 6 && navigate('listing', { id: current.id })}
              style={{
                transform: `translateX(${dragX}px) rotate(${angle}deg)`,
                transition: dragging ? 'none' : 'transform .25s ease',
                cursor: 'grab', touchAction: 'pan-y',
              }}
              likeOpacity={likeOpacity}
              passOpacity={passOpacity}
            />
          </>
        ) : (
          <div style={{ position: 'absolute', inset: 20, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', color: '#fff' }}>
            <div style={{ width: 80, height: 80, borderRadius: 999, background: 'rgba(255,255,255,.1)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 20, color: 'var(--primary)' }}>
              <I.check style={{ width: 40, height: 40 }} />
            </div>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 32, margin: 0 }}>Alles durch!</h2>
            <p style={{ color: 'rgba(255,255,255,.6)', marginTop: 8, fontSize: 14 }}>
              Sie haben alle Inserate gesehen. Neue Treffer erhalten Sie als Mitteilung.
            </p>
            <button onClick={() => setIdx(0)} className="btn btn-accent" style={{ marginTop: 20 }}>Von vorn beginnen</button>
          </div>
        )}
      </div>

      {/* Action buttons */}
      {current && (
        <div style={{ padding: '20px 40px 40px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 20 }}>
          <ActionBtn onClick={() => decide('pass')} color="#fff" bg="rgba(255,255,255,.12)" size={56}>
            <I.x style={{ width: 26, height: 26, strokeWidth: 2.5 }} />
          </ActionBtn>
          <ActionBtn onClick={() => navigate('listing', { id: current.id })} color="#1F1A14" bg="#fff" size={48}>
            <I.search style={{ width: 22, height: 22 }} />
          </ActionBtn>
          <ActionBtn onClick={() => decide('like')} color="#fff" bg="var(--primary)" size={56}>
            <I.heartFill style={{ width: 26, height: 26 }} />
          </ActionBtn>
        </div>
      )}
    </div>
  );
}

function ActionBtn({ children, onClick, color, bg, size = 56 }) {
  return (
    <button onClick={onClick} style={{
      width: size, height: size, borderRadius: 999, border: 0, cursor: 'pointer',
      background: bg, color, display: 'flex', alignItems: 'center', justifyContent: 'center',
      boxShadow: '0 6px 16px rgba(0,0,0,.25)',
    }}>{children}</button>
  );
}

function SwipeCard({ listing, onStart, onMove, onEnd, onTap, style, likeOpacity = 0, passOpacity = 0 }) {
  return (
    <div
      onMouseDown={onStart} onMouseMove={onMove} onMouseUp={onEnd} onMouseLeave={onEnd}
      onTouchStart={onStart} onTouchMove={onMove} onTouchEnd={onEnd}
      onClick={onTap}
      style={{
        position: 'absolute', inset: 0, borderRadius: 24, overflow: 'hidden',
        background: '#fff', boxShadow: '0 20px 40px rgba(0,0,0,.3)',
        ...style,
      }}
    >
      <div className="photo" style={{
        position: 'absolute', inset: 0,
        backgroundImage: `url(${listing.photos[0]})`,
      }} />
      <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(0deg, rgba(0,0,0,.85) 0%, transparent 55%)' }} />

      {/* Like/Pass overlays */}
      <div style={{
        position: 'absolute', top: 30, left: 22, padding: '8px 18px',
        border: '3px solid var(--primary)', color: 'var(--primary)',
        fontWeight: 800, fontSize: 22, borderRadius: 10, transform: 'rotate(-10deg)',
        opacity: likeOpacity, background: 'rgba(255,255,255,.85)',
      }}>MERKEN</div>
      <div style={{
        position: 'absolute', top: 30, right: 22, padding: '8px 18px',
        border: '3px solid #fff', color: '#fff',
        fontWeight: 800, fontSize: 22, borderRadius: 10, transform: 'rotate(10deg)',
        opacity: passOpacity, background: 'rgba(0,0,0,.4)',
      }}>WEITER</div>

      {/* Badge top */}
      <div style={{ position: 'absolute', top: 16, left: 16, display: 'flex', gap: 6 }}>
        <PlatformBadge platform={listing.platform} />
        {listing.provisionsfrei && <span style={{ background: 'rgba(255,255,255,.92)', color: 'var(--ink)', padding: '3px 8px', borderRadius: 999, fontSize: 10, fontWeight: 700 }}>PROVISIONSFREI</span>}
      </div>
      {listing.aiScore !== null && listing.aiScore !== undefined && (
        <div style={{
          position: 'absolute', top: 14, right: 14,
          width: 52, height: 52, borderRadius: 999,
          background: listing.aiScore >= 80 ? '#2F8F5A' : listing.aiScore >= 60 ? '#C28428' : '#C8331C',
          color: '#fff', fontSize: 17, fontWeight: 800,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: '0 4px 12px rgba(0,0,0,.3)', flexDirection: 'column', lineHeight: 1,
        }}>
          {listing.aiScore}
          <div style={{ fontSize: 7, fontWeight: 600, opacity: .9, marginTop: 2, letterSpacing: 0.05 }}>KI-SCORE</div>
        </div>
      )}

      {/* Body */}
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '20px 22px 26px', color: '#fff' }}>
        <div style={{ fontFamily: 'var(--font-display)', fontSize: 30, fontWeight: 400, letterSpacing: -0.02, lineHeight: 1.0 }}>
          {fmtPriceShort(listing.price)}
        </div>
        <div style={{ fontSize: 16, fontWeight: 600, marginTop: 6 }}>{listing.title}</div>
        <div style={{ fontSize: 13, color: 'rgba(255,255,255,.8)', marginTop: 4, display: 'flex', alignItems: 'center', gap: 4 }}>
          <I.pin style={{ width: 13, height: 13 }} /> {listing.district}, {listing.city}
        </div>
        <div style={{ display: 'flex', gap: 14, marginTop: 12, fontSize: 13, fontWeight: 500 }}>
          <span style={{ display: 'flex', alignItems: 'center', gap: 4 }}><I.ruler style={{ width: 14, height: 14 }} /> {fmtArea(listing.area)}</span>
          <span style={{ display: 'flex', alignItems: 'center', gap: 4 }}><I.bed style={{ width: 14, height: 14 }} /> {listing.rooms} Zi.</span>
          <span style={{ display: 'flex', alignItems: 'center', gap: 4 }}><I.calendar style={{ width: 14, height: 14 }} /> {listing.baujahr}</span>
        </div>
      </div>
    </div>
  );
}

// ─── PORTFOLIO (favorites + archive) ───────────────────────────────────
function PortfolioScreen({ ctx }) {
  const { listings, favs, archived, navigate, toggleFav, portfolioAnalytics, loadPortfolioAnalytics, exportPortfolio, busy } = ctx;
  const [tab, setTab] = React.useState('favs');
  const [loaded, setLoaded] = React.useState(false);
  const favList = listings.filter(l => favs.has(l.id));
  const archiveList = listings.filter(l => archived.has(l.id));
  const totalValue = favList.filter(l => l.type === 'kauf').reduce((s, l) => s + l.price, 0);
  const avgScore = (() => {
    const xs = favList.filter(l => l.aiScore);
    return xs.length ? Math.round(xs.reduce((s,l) => s+l.aiScore, 0) / xs.length) : null;
  })();
  const analytics = portfolioAnalytics;
  const summary = analytics?.summary || {};
  const bestYield = (analytics?.yields || []).reduce((best, item) => {
    const value = Math.max(item.gross_yield || 0, item.net_yield || 0, item.cap_rate || 0);
    return value > (best.value || 0) ? { ...item, value } : best;
  }, {});

  React.useEffect(() => {
    if (!loaded) {
      setLoaded(true);
      loadPortfolioAnalytics?.().catch(() => {});
    }
  }, [loaded]);

  return (
    <div className="phone-scroll fade-in" style={{ paddingBottom: 100, background: 'var(--bg)' }}>
      <div style={{ padding: '60px 20px 0' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 16 }}>
          <div>
            <div style={{ fontSize: 13, color: 'var(--ink-muted)', fontWeight: 500 }}>Meine Auswahl</div>
            <h1 style={{ margin: '6px 0 0', fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 38, lineHeight: 1.0, letterSpacing: -0.025 }}>
              Merkliste
            </h1>
          </div>
          <button onClick={() => navigate('investor')} className="btn btn-soft" style={{ padding: '10px 13px', fontSize: 13 }}>
            <I.trend style={{ width: 16, height: 16 }} /> Investor
          </button>
        </div>
      </div>

      {/* Analytics */}
      <div style={{ padding: '20px 16px 0', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <StatTile value={summary.count ?? favList.length} label="Gemerkt" delta={`${favList.filter(l=>l.type==='kauf').length} Kauf · ${favList.filter(l=>l.type==='miete').length} Miete`} />
        <StatTile value={fmtMetricPrice(summary.totalValue ?? totalValue)} label="Gesamtvolumen" delta="nur Kaufobjekte" accent />
        <StatTile value={summary.averageScore ? `Ø ${summary.averageScore}` : (avgScore ? `Ø ${avgScore}` : '—')} label="KI-Score Mittelw." />
        <StatTile value={archiveList.length} label="Archiviert" />
      </div>

      <div style={{ padding: '18px 16px 0' }}>
        <div className="card" style={{ padding: 16, background: 'linear-gradient(135deg, var(--surface) 0%, var(--primary-soft) 100%)' }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
            <div>
              <div style={{ fontSize: 12, fontWeight: 800, color: 'var(--primary-ink)', textTransform: 'uppercase', letterSpacing: 0.04 }}>Portfolio-Analytics</div>
              <div style={{ marginTop: 7, fontFamily: 'var(--font-display)', fontSize: 25, lineHeight: 1.05, color: 'var(--ink)' }}>
                {summary.estimatedAnnualIncome ? `${fmtMetricPrice(summary.estimatedAnnualIncome)} pot. Jahresmiete` : 'Rendite-Ansicht aktiv'}
              </div>
              <div style={{ marginTop: 6, fontSize: 12, lineHeight: 1.5, color: 'var(--ink-muted)' }}>
                {bestYield.label ? `${bestYield.label}: bester Renditewert ${fmtPct(bestYield.value)}` : 'Gemerkt-Kaufobjekte werden mit den alten Investment-Metriken bewertet.'}
              </div>
            </div>
            <div style={{ width: 42, height: 42, borderRadius: 13, background: 'var(--ink)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
              <I.euro style={{ width: 21, height: 21 }} />
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginTop: 14 }}>
            <PortfolioMini label="Brutto" value={fmtPct(summary.averageGrossYield)} />
            <PortfolioMini label="Netto" value={fmtPct(summary.averageNetYield)} />
            <PortfolioMini label="Preis Ø" value={fmtMetricPrice(summary.averagePrice)} />
          </div>
          <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
            <button onClick={() => navigate('investor')} className="btn btn-primary" style={{ flex: 1, fontSize: 13, padding: '11px 12px' }}>
              Top-Deals öffnen
            </button>
            <button onClick={exportPortfolio} disabled={busy || !favList.length} className="btn btn-outline" style={{ flex: 1, fontSize: 13, padding: '11px 12px', opacity: !favList.length ? .55 : 1 }}>
              <I.download style={{ width: 16, height: 16 }} /> CSV
            </button>
          </div>
        </div>
      </div>

      {/* Tabs */}
      <div style={{ padding: '24px 16px 0', display: 'flex', gap: 8, alignItems: 'center' }}>
        <TabBtn active={tab==='favs'} onClick={() => setTab('favs')}>
          <I.heartFill style={{ width: 14, height: 14 }} /> Gemerkt ({favList.length})
        </TabBtn>
        <TabBtn active={tab==='archive'} onClick={() => setTab('archive')}>
          <I.archive style={{ width: 14, height: 14 }} /> Archiv ({archiveList.length})
        </TabBtn>
      </div>

      <div style={{ padding: '16px 16px 0' }}>
        {(tab==='favs' ? favList : archiveList).length === 0 ? (
          <EmptyState
            icon={tab==='favs' ? <I.heart /> : <I.archive />}
            title={tab==='favs' ? 'Noch nichts gemerkt' : 'Archiv ist leer'}
            subtitle={tab==='favs' ? 'Tippen Sie auf das Herz, um Inserate hier zu sammeln.' : 'Verschobene Inserate landen hier.'}
          />
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {(tab==='favs' ? favList : archiveList).map(l => (
              <ListingCard key={l.id} listing={l} onTap={() => navigate('listing', { id: l.id })} isFav={favs.has(l.id)} onFav={toggleFav} compact />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function TabBtn({ active, onClick, children }) {
  return (
    <button onClick={onClick} className="chip" style={{
      padding: '8px 14px', fontSize: 13,
      background: active ? 'var(--ink)' : 'var(--surface)',
      color: active ? '#fff' : 'var(--ink-2)',
      border: active ? 'none' : '1px solid var(--border)',
    }}>{children}</button>
  );
}
function PortfolioMini({ label, value }) {
  return (
    <div style={{ background: 'rgba(255,255,255,.66)', border: '1px solid rgba(255,255,255,.72)', borderRadius: 12, padding: '10px 8px' }}>
      <div style={{ fontSize: 10, fontWeight: 800, color: 'var(--ink-muted)', textTransform: 'uppercase', letterSpacing: 0.04 }}>{label}</div>
      <div style={{ marginTop: 4, fontSize: 16, fontWeight: 800, color: 'var(--ink)', fontVariantNumeric: 'tabular-nums' }}>{value || '—'}</div>
    </div>
  );
}

// ─── NOTIFICATIONS ─────────────────────────────────────────────────────
function NotificationsScreen({ ctx }) {
  const {
    notifications, navigate, setNotifications, searches, notificationSettings,
    loadNotificationSettings, storePushSubscription, revokePushSubscription,
    revokeAllPushSubscriptions, sendTestNotification, busy,
  } = ctx;
  const [pushMessage, setPushMessage] = React.useState(null);
  const [pushBusy, setPushBusy] = React.useState(false);
  const pushSupported = typeof window !== 'undefined'
    && 'serviceWorker' in navigator
    && 'PushManager' in window
    && 'Notification' in window;

  React.useEffect(() => {
    loadNotificationSettings?.().catch(() => {});
  }, []);

  const markAll = () => setNotifications(notifications.map(n => ({ ...n, read: true })));
  const click = (n) => {
    setNotifications(notifications.map(x => x.id === n.id ? { ...x, read: true } : x));
    if (n.listingId) navigate('listing', { id: n.listingId });
    else if (n.searchId) {
      const s = searches.find(x => x.id === n.searchId);
      if (s) {
        if (s.category === 'kauf') navigate('results', { searchId: n.searchId });
        else navigate('mietenResults', { searchId: n.searchId });
      }
    }
  };
  const enablePush = async () => {
    setPushMessage(null);
    if (!pushSupported) {
      setPushMessage('Dieser Browser unterstützt keine Push-Benachrichtigungen.');
      return;
    }
    if (!notificationSettings?.vapidPublicKey) {
      setPushMessage('Der VAPID-Schluessel ist auf dem Server nicht konfiguriert.');
      return;
    }

    setPushBusy(true);
    try {
      const permission = await Notification.requestPermission();
      if (permission !== 'granted') {
        setPushMessage('Benachrichtigungen wurden im Browser nicht erlaubt.');
        return;
      }

      const registration = await navigator.serviceWorker.register('/sw.js');
      await navigator.serviceWorker.ready;
      const existing = await registration.pushManager.getSubscription();
      if (existing) {
        await storePushSubscription(existing.toJSON());
      } else {
        const subscription = await registration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: urlBase64ToUint8Array(notificationSettings.vapidPublicKey),
        });
        await storePushSubscription(subscription.toJSON());
      }
      setPushMessage('Dieses Gerät ist jetzt für Push aktiviert.');
    } catch (err) {
      setPushMessage(err.message || 'Push konnte nicht aktiviert werden.');
    } finally {
      setPushBusy(false);
    }
  };
  const removeDevice = async (endpoint) => {
    setPushMessage(null);
    await revokePushSubscription(endpoint);
  };
  const removeAll = async () => {
    setPushMessage(null);
    await revokeAllPushSubscriptions();
  };

  return (
    <div className="phone-scroll fade-in" style={{ paddingBottom: 100, background: 'var(--bg)' }}>
      <div style={{ padding: '60px 20px 0', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
        <div>
          <div style={{ fontSize: 13, color: 'var(--ink-muted)', fontWeight: 500 }}>Aktivitäten</div>
          <h1 style={{ margin: '6px 0 0', fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 38, lineHeight: 1.0, letterSpacing: -0.025 }}>
            Mitteilungen
          </h1>
        </div>
        <button onClick={markAll} style={{ background: 'transparent', border: 0, color: 'var(--primary)', fontSize: 13, fontWeight: 600, cursor: 'pointer', padding: 0 }}>
          Alle gelesen
        </button>
      </div>

      {/* Push subscription card */}
      <div style={{ padding: '20px 16px 0' }}>
        <div className="card" style={{ padding: 14 }}>
          <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
            <div style={{
              width: 40, height: 40, borderRadius: 12,
              background: notificationSettings?.hasSubscriptions ? 'var(--primary)' : 'var(--surface-2)',
              color: notificationSettings?.hasSubscriptions ? '#fff' : 'var(--ink-muted)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}><I.bell /></div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink)' }}>Browser-Push</div>
              <div style={{ fontSize: 12, color: 'var(--ink-muted)', marginTop: 2 }}>
                {notificationSettings?.hasSubscriptions
                  ? `${notificationSettings.subscriptions.length} Gerät(e) aktiv`
                  : 'Noch kein Gerät verbunden.'}
              </div>
            </div>
            <button onClick={enablePush} disabled={pushBusy || busy || !pushSupported} className="btn btn-accent" style={{ padding: '9px 12px', fontSize: 12, opacity: (!pushSupported || pushBusy || busy) ? .65 : 1 }}>
              Aktivieren
            </button>
          </div>
          <div style={{ marginTop: 12, paddingTop: 12, borderTop: '0.5px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 10 }}>
            {!pushSupported && (
              <div style={{ fontSize: 12, color: 'var(--ink-muted)', lineHeight: 1.5 }}>Push ist in diesem Browser nicht verfügbar.</div>
            )}
            {pushMessage && (
              <div style={{ fontSize: 12, color: pushMessage.includes('nicht') || pushMessage.includes('konnte') ? 'var(--danger)' : 'var(--success)', fontWeight: 700, lineHeight: 1.5 }}>
                {pushMessage}
              </div>
            )}
            {(notificationSettings?.subscriptions || []).length === 0 ? (
              <div style={{ fontSize: 12, color: 'var(--ink-muted)', lineHeight: 1.5 }}>
                Aktivieren Sie Push für dieses Gerät, damit neue Treffer und hohe KI-Bewertungen sofort ankommen.
              </div>
            ) : (
              notificationSettings.subscriptions.map(device => (
                <PushDeviceRow key={device.id} device={device} onRemove={() => removeDevice(device.endpoint)} />
              ))
            )}
            <div style={{ display: 'flex', gap: 8 }}>
              <button onClick={sendTestNotification} disabled={busy || !notificationSettings?.hasSubscriptions} className="btn btn-soft" style={{ flex: 1, padding: '10px 12px', fontSize: 12, opacity: !notificationSettings?.hasSubscriptions ? .55 : 1 }}>
                Test senden
              </button>
              <button onClick={removeAll} disabled={busy || !notificationSettings?.hasSubscriptions} className="btn btn-outline" style={{ flex: 1, padding: '10px 12px', fontSize: 12, opacity: !notificationSettings?.hasSubscriptions ? .55 : 1 }}>
                Alle entfernen
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* Stream */}
      <div style={{ padding: '24px 16px 0' }}>
        <h3 className="section-title" style={{ marginBottom: 10 }}>Letzte Aktivität</h3>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {notifications.map(n => (
            <NotifRow key={n.id} n={n} onClick={() => click(n)} />
          ))}
        </div>
      </div>
    </div>
  );
}
function PrefRow({ label, on, onClick }) {
  return (
    <div onClick={onClick} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', cursor: 'pointer' }}>
      <span style={{ fontSize: 13, color: 'var(--ink-2)' }}>{label}</span>
      <Toggle on={on} />
    </div>
  );
}
function PushDeviceRow({ device, onRemove }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 0', borderTop: '0.5px solid var(--border)' }}>
      <div style={{ width: 34, height: 34, borderRadius: 10, background: 'var(--primary-soft)', color: 'var(--primary-ink)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
        <I.shield style={{ width: 17, height: 17 }} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 800, color: 'var(--ink)' }}>{device.label}</div>
        <div style={{ fontSize: 11, color: 'var(--ink-muted)', marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {device.endpointPreview}
        </div>
      </div>
      <button onClick={onRemove} className="btn btn-soft" style={{ padding: '8px 10px', color: 'var(--danger)', fontSize: 12 }}>
        Entfernen
      </button>
    </div>
  );
}
function urlBase64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);
  for (let i = 0; i < rawData.length; i += 1) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}
function NotifRow({ n, onClick }) {
  const icons = {
    'ai-high':   { i: <I.spark />,   bg: 'var(--primary-soft)', c: 'var(--primary-ink)' },
    'new-match': { i: <I.search />,  bg: 'var(--info-soft)',    c: 'var(--info)' },
    'system':    { i: <I.shield />,  bg: 'var(--surface-2)',    c: 'var(--ink-muted)' },
  };
  const cfg = icons[n.kind] || icons.system;
  return (
    <div onClick={onClick} className="card" style={{
      padding: 14, display: 'flex', gap: 12, alignItems: 'flex-start', cursor: 'pointer',
      background: n.read ? 'var(--surface)' : 'var(--surface)',
      borderLeft: n.read ? '0' : '3px solid var(--primary)',
      paddingLeft: n.read ? 14 : 11,
    }}>
      <div style={{ width: 36, height: 36, borderRadius: 10, background: cfg.bg, color: cfg.c, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{cfg.i}</div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
          <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink)' }}>{n.title}</div>
          {!n.read && <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--primary)' }} />}
        </div>
        <div style={{ fontSize: 12, color: 'var(--ink-muted)', marginTop: 4, lineHeight: 1.5 }}>{n.body}</div>
        <div style={{ fontSize: 11, color: 'var(--ink-faint)', marginTop: 6 }}>{fmtRelative(n.at)}</div>
      </div>
    </div>
  );
}

// ─── PROFILE ───────────────────────────────────────────────────────────
const RENTAL_PROFILE_DEFAULTS = {
  personalized_inquiry_enabled: true,
  full_name: '',
  age: '',
  profession: '',
  current_city: '',
  move_reason: '',
  household: '',
  smoking: '',
  pets: '',
  employment: '',
  monthly_net_income: '',
  documents: '',
  rental_intent: '',
  availability: '',
  additional_notes: '',
};

const RENTAL_PROFILE_FIELDS = [
  ['full_name', 'Name'],
  ['age', 'Alter'],
  ['profession', 'Beruf'],
  ['current_city', 'Aktueller Ort'],
  ['household', 'Haushalt'],
  ['monthly_net_income', 'Nettoeinkommen'],
  ['smoking', 'Rauchen'],
  ['pets', 'Haustiere'],
  ['employment', 'Arbeitsverhältnis'],
  ['documents', 'Unterlagen', 'textarea'],
  ['move_reason', 'Suchgrund', 'textarea'],
  ['rental_intent', 'Mietabsicht', 'textarea'],
  ['availability', 'Besichtigung', 'textarea'],
  ['additional_notes', 'Weitere Hinweise', 'textarea'],
];

function rentalInquiryPersonalizationEnabled(profile = {}) {
  const value = profile.personalized_inquiry_enabled;
  return !(value === false || value === 'false' || value === 0 || value === '0');
}

function ProfileScreen({ ctx }) {
  const { navigate, reset, setTab, signOut, user, plan, taskLimit, updateProfile, toggleExpertMode, busy, resendVerification, startCheckout, openBillingPortal, connectTelegram, disconnectTelegram } = ctx;
  const accountRef = React.useRef(null);
  const inquiryRef = React.useRef(null);
  const [integrationsOpen, setIntegrationsOpen] = React.useState(false);
  const [profile, setProfile] = React.useState(() => ({
    name: user?.name || '',
    email: user?.email || '',
    telegram_chat_id: user?.telegram_chat_id || '',
    ebay_userid: user?.ebay_userid || '',
    ebay_contactname: user?.ebay_contactname || '',
    ebay_email: user?.ebay_email || '',
    ebay_password: '',
    default_reply_message: user?.default_reply_message || '',
    rental_profile: { ...RENTAL_PROFILE_DEFAULTS, ...(user?.rental_profile || {}) },
  }));
  const [localMessage, setLocalMessage] = React.useState(null);
  const [verificationSent, setVerificationSent] = React.useState(false);
  const [telegramPending, setTelegramPending] = React.useState(false);
  const setField = (key, value) => setProfile(p => ({ ...p, [key]: value }));
  const setRentalProfileField = (key, value) => setProfile(p => ({
    ...p,
    rental_profile: { ...RENTAL_PROFILE_DEFAULTS, ...(p.rental_profile || {}), [key]: value },
  }));
  const scrollToAccount = () => accountRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  const scrollToInquiry = () => inquiryRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  React.useEffect(() => {
    const shouldScroll = sessionStorage.getItem('immobotScrollInquiryProfile') === '1'
      || window.location.hash.includes('inquiry=1')
      || window.location.search.includes('inquiry=1');
    if (!shouldScroll) return;
    sessionStorage.removeItem('immobotScrollInquiryProfile');
    setTimeout(scrollToInquiry, 120);
  }, []);
  const goToActiveSearches = () => {
    setTab?.('immobilien');
    reset?.('dashboard');
  };
  const saveProfile = async () => {
    setLocalMessage(null);
    await updateProfile(profile);
    setLocalMessage('Gespeichert');
    setField('ebay_password', '');
  };

  return (
    <div className="phone-scroll fade-in" style={{ paddingBottom: 100, background: 'var(--bg)' }}>
      <div style={{ padding: '60px 20px 0' }}>
        <h1 style={{ margin: 0, fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 38, lineHeight: 1.0, letterSpacing: -0.025 }}>
          Profil
        </h1>
      </div>

      {/* User card */}
      <div style={{ padding: '20px 16px 0' }}>
        <div className="card" style={{ padding: 16, display: 'flex', gap: 14, alignItems: 'center' }}>
          <div style={{
            width: 58, height: 58, borderRadius: 999,
            background: 'linear-gradient(135deg, var(--primary), var(--primary-deep))',
            color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: 'var(--font-display)', fontSize: 28, fontWeight: 400,
          }}>{user?.initials || 'I'}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 17, fontWeight: 700, color: 'var(--ink)', letterSpacing: -0.01 }}>{user?.name || 'ImmoBot Nutzer'}</div>
            <div style={{ fontSize: 13, color: 'var(--ink-muted)' }}>{user?.email}</div>
            <div style={{ marginTop: 6, display: 'inline-flex', alignItems: 'center', gap: 5 }}>
              <span className="chip chip-accent" style={{ fontSize: 11 }}><I.flame style={{ width: 12, height: 12 }} /> {user?.isAdmin ? 'Admin' : 'Aktiv'}</span>
            </div>
          </div>
        </div>
      </div>

      {/* Email verification banner */}
      {user && user.emailVerified === false && (
        <div style={{ padding: '20px 16px 0' }}>
          <div className="card" style={{ padding: 16, border: '1px solid var(--warning, #f0b429)', background: 'rgba(240,180,41,.08)' }}>
            <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink)' }}>E-Mail-Adresse bestätigen</div>
            <div style={{ fontSize: 13, color: 'var(--ink-muted)', marginTop: 4 }}>
              Bitte bestätige deine E-Mail-Adresse, um Suchen anzulegen und Benachrichtigungen zu erhalten.
            </div>
            <button
              onClick={async () => { await resendVerification(); setVerificationSent(true); }}
              disabled={busy || verificationSent}
              className="btn btn-primary"
              style={{ marginTop: 10, fontSize: 13, padding: '8px 14px', opacity: verificationSent ? .7 : 1 }}
            >
              {verificationSent ? 'E-Mail gesendet ✓' : 'Bestätigungs-E-Mail senden'}
            </button>
          </div>
        </div>
      )}

      {/* Plan & token card */}
      <div style={{ padding: '20px 16px 0' }}>
        <div className="card" style={{ padding: 16, background: 'linear-gradient(135deg, var(--ink) 0%, var(--ink-2) 100%)', color: '#fff' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
            <div>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--primary)', textTransform: 'uppercase', letterSpacing: 0.05 }}>Dein Plan</div>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 28, fontWeight: 400, letterSpacing: -0.01, marginTop: 4 }}>{plan?.label || 'Free'}</div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: -0.01 }}>
                {plan?.tokens_unlimited ? '∞' : (plan?.tokens_balance ?? 0)}
              </div>
              <div style={{ fontSize: 11, color: 'rgba(255,255,255,.55)' }}>Tokens übrig</div>
            </div>
          </div>
          <div style={{ display: 'flex', gap: 14, marginTop: 14, fontSize: 12, color: 'rgba(255,255,255,.7)', flexWrap: 'wrap' }}>
            <span>{taskLimit?.remaining_slots == null ? 'Unbegr. Suchen' : `${taskLimit.remaining_slots} Such-Slots frei`}</span>
            <span>{taskLimit?.remaining_evaluations == null ? 'Unbegr. KI' : `${taskLimit.remaining_evaluations} KI-Bewertungen heute`}</span>
            {!plan?.tokens_unlimited && plan?.tokens_reset_at && (
              <span>Neue Tokens am {new Date(plan.tokens_reset_at).toLocaleDateString('de-DE')}</span>
            )}
          </div>
          {!plan?.tokens_unlimited && (plan?.tokens_balance ?? 0) <= 3 && (
            <div style={{ marginTop: 12, fontSize: 12, color: '#ffd28a' }}>
              {plan?.tokens_balance <= 0
                ? 'Deine Tokens sind aufgebraucht — neue Treffer werden nicht mehr gemeldet.'
                : 'Deine Tokens sind fast aufgebraucht.'} Mit Premium erhältst du unbegrenzte Sofort-Benachrichtigungen.
            </div>
          )}
          <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
            {plan?.key !== 'premium' && plan?.billing_configured && (
              <button onClick={startCheckout} disabled={busy} className="btn btn-accent" style={{ flex: 1, fontSize: 13, padding: '10px' }}>
                ⚡ Premium holen
              </button>
            )}
            {plan?.key === 'premium' && plan?.billing_configured && !user?.isAdmin && (
              <button onClick={openBillingPortal} disabled={busy} className="btn btn-soft" style={{ flex: 1, background: 'rgba(255,255,255,.12)', color: '#fff', fontSize: 13, padding: '10px' }}>
                Abo verwalten
              </button>
            )}
            <button onClick={toggleExpertMode} className="btn btn-soft" style={{ flex: 1, background: 'rgba(255,255,255,.12)', color: '#fff', fontSize: 13, padding: '10px' }}>
              Expert {user?.expertMode ? 'aus' : 'an'}
            </button>
          </div>
        </div>
      </div>

      <div ref={accountRef} style={{ padding: '20px 16px 0', scrollMarginTop: 12 }}>
        <h3 className="section-title" style={{ marginBottom: 8 }}>Persönliche Daten</h3>
        <div className="card" style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>
          <ProfileInput label="Name" value={profile.name} onChange={v => setField('name', v)} />
          <ProfileInput label="E-Mail" value={profile.email} onChange={v => setField('email', v)} type="email" />
          <div>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-muted)', marginBottom: 6, textTransform: 'uppercase' }}>Standardnachricht</div>
            <textarea value={profile.default_reply_message} onChange={e => setField('default_reply_message', e.target.value)} style={{ width: '100%', minHeight: 92, padding: 12, borderRadius: 12, border: '1px solid var(--border)', background: 'var(--surface-2)', fontFamily: 'var(--font-sans)', resize: 'vertical' }} />
          </div>
          <div ref={inquiryRef} style={{ scrollMarginTop: 12 }}>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-muted)', marginBottom: 8, textTransform: 'uppercase' }}>Anfrageprofil</div>
            <InquiryProfileFields value={profile.rental_profile} onChange={setRentalProfileField} />
          </div>
          <button type="button" onClick={() => setIntegrationsOpen(true)} className="btn btn-outline" style={{ width: '100%' }}>
            Schnittstellen verwalten
          </button>
          {localMessage && <div style={{ fontSize: 12, color: 'var(--success)', fontWeight: 700 }}>{localMessage}</div>}
          <button onClick={saveProfile} disabled={busy} className="btn btn-primary" style={{ width: '100%', opacity: busy ? .7 : 1 }}>
            Profil speichern
          </button>
        </div>
      </div>

      {/* Menu */}
      <div style={{ padding: '24px 16px 0' }}>
        <h3 className="section-title" style={{ marginBottom: 8 }}>Konto</h3>
        <div className="card" style={{ overflow: 'hidden' }}>
          <ProfileRow icon={<I.user />} title="Persönliche Daten" detail="bearbeiten" onTap={scrollToAccount} />
          <ProfileRow icon={<I.globe />} title="Schnittstellen" detail="Telegram, Kleinanzeigen" onTap={() => setIntegrationsOpen(true)} />
          <ProfileRow icon={<I.trend />} title="Investor-Ansicht" detail="Top-Deals" onTap={() => navigate('investor')} />
          <ProfileRow icon={<I.bell />} title="Benachrichtigungen" onTap={() => navigate('notifications', null, true)} />
          {user?.isAdmin && <ProfileRow icon={<I.settings />} title="Job-Monitor (Admin)" onTap={() => navigate('admin')} />}
          <ProfileRow icon={<I.shield />} title="Sicherheit & Konto" onTap={() => navigate('security')} isLast />
        </div>
      </div>
      <div style={{ padding: '16px 16px 0' }}>
        <h3 className="section-title" style={{ marginBottom: 8 }}>Such-Voreinstellungen</h3>
        <div className="card" style={{ overflow: 'hidden' }}>
          <ProfileRow icon={<I.home />} title="Aktive Suchen" detail={String(taskLimit?.current_tasks ?? 0)} onTap={goToActiveSearches} />
          <ProfileRow icon={<I.spark />} title="Expert-Modus" detail={user?.expertMode ? 'Ein' : 'Aus'} onTap={toggleExpertMode} />
          <ProfileRow icon={<I.globe />} title="Sprache" detail="Deutsch" onTap={() => setLocalMessage('Sprache ist bereits auf Deutsch eingestellt.')} isLast />
        </div>
      </div>
      <div style={{ padding: '16px 16px 0' }}>
        <div className="card" style={{ overflow: 'hidden' }}>
          <ProfileRow icon={<I.logout />} title="Abmelden" danger onTap={signOut} isLast />
        </div>
      </div>
      <Sheet open={integrationsOpen} onClose={() => setIntegrationsOpen(false)} title="Schnittstellen" height="72%">
        <div style={{ padding: '4px 20px 24px', display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-muted)', marginBottom: 6, textTransform: 'uppercase' }}>Telegram</div>
            {user?.telegram_connected ? (
              <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                <span className="chip chip-accent" style={{ fontSize: 12 }}>✓ Verbunden</span>
                <button onClick={disconnectTelegram} disabled={busy} className="btn btn-outline" style={{ fontSize: 12, padding: '6px 12px' }}>Trennen</button>
              </div>
            ) : (
              <div>
                <button
                  onClick={async () => { await connectTelegram(); setTelegramPending(true); }}
                  disabled={busy}
                  className="btn btn-primary"
                  style={{ width: '100%', fontSize: 13 }}
                >
                  Mit Telegram verbinden
                </button>
                {telegramPending && (
                  <div style={{ fontSize: 12, color: 'var(--ink-muted)', marginTop: 8 }}>
                    Telegram wurde geöffnet — tippe dort auf „Start“. Danach hier neu laden.
                  </div>
                )}
              </div>
            )}
          </div>
          {user?.expertMode && (
            <ProfileInput label="Telegram Chat-ID (manuell)" value={profile.telegram_chat_id} onChange={v => setField('telegram_chat_id', v)} />
          )}
          <ProfileInput label="Kleinanzeigen User-ID" value={profile.ebay_userid} onChange={v => setField('ebay_userid', v)} />
          <ProfileInput label="Kontaktname" value={profile.ebay_contactname} onChange={v => setField('ebay_contactname', v)} />
          <ProfileInput label="Kleinanzeigen E-Mail" value={profile.ebay_email} onChange={v => setField('ebay_email', v)} type="email" />
          <ProfileInput label="Kleinanzeigen Passwort" value={profile.ebay_password} onChange={v => setField('ebay_password', v)} type="password" placeholder="Unverändert lassen" />
          <button onClick={async () => { await saveProfile(); setIntegrationsOpen(false); }} disabled={busy} className="btn btn-primary" style={{ width: '100%', opacity: busy ? .7 : 1, marginTop: 4 }}>
            Schnittstellen speichern
          </button>
        </div>
      </Sheet>

      <div style={{ textAlign: 'center', padding: '24px 0 0', fontSize: 11, color: 'var(--ink-faint)' }}>
        ImmoBot v3.4.1 · Build 2026.05.13
      </div>
    </div>
  );
}
function ProfileInput({ label, value, onChange, type = 'text', placeholder }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <span style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-muted)', textTransform: 'uppercase' }}>{label}</span>
      <input
        value={value || ''}
        onChange={e => onChange(e.target.value)}
        type={type}
        placeholder={placeholder}
        style={{
          width: '100%', padding: '11px 12px', borderRadius: 12,
          border: '1px solid var(--border)', background: 'var(--surface-2)',
          color: 'var(--ink)', fontFamily: 'var(--font-sans)', fontSize: 14,
        }}
      />
    </label>
  );
}
function ProfileTextarea({ label, value, onChange, placeholder }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <span style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-muted)', textTransform: 'uppercase' }}>{label}</span>
      <textarea
        value={value || ''}
        onChange={e => onChange(e.target.value)}
        placeholder={placeholder}
        rows={2}
        style={{
          width: '100%', minHeight: 74, padding: '11px 12px', borderRadius: 12,
          border: '1px solid var(--border)', background: 'var(--surface-2)',
          color: 'var(--ink)', fontFamily: 'var(--font-sans)', fontSize: 14,
          resize: 'vertical', boxSizing: 'border-box',
        }}
      />
    </label>
  );
}
function InquiryProfileFields({ value = {}, onChange = () => {}, columns = 1 }) {
  const profile = { ...RENTAL_PROFILE_DEFAULTS, ...(value || {}) };
  const enabled = rentalInquiryPersonalizationEnabled(profile);
  return (
    <div style={{ display: 'grid', gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`, gap: 10 }}>
      <label style={{
        gridColumn: '1 / -1',
        display: 'flex',
        alignItems: 'center',
        gap: 12,
        padding: 12,
        borderRadius: 12,
        background: 'var(--surface-2)',
        border: '1px solid var(--border)',
      }}>
        <input
          type="checkbox"
          checked={enabled}
          onChange={e => onChange('personalized_inquiry_enabled', e.target.checked)}
          style={{ width: 18, height: 18, accentColor: 'var(--primary)', flexShrink: 0 }}
        />
        <span style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          <span style={{ fontSize: 13, fontWeight: 800, color: 'var(--ink)' }}>Codex-Personalisierung</span>
          <span style={{ fontSize: 12, color: 'var(--ink-muted)', lineHeight: 1.35 }}>
            Wenn deaktiviert, wird nur die normale Standardnachricht genutzt.
          </span>
        </span>
      </label>
      {RENTAL_PROFILE_FIELDS.map(([key, label, type]) => (
        type === 'textarea'
          ? <ProfileTextarea key={key} label={label} value={profile[key]} onChange={v => onChange(key, v)} />
          : <ProfileInput key={key} label={label} value={profile[key]} onChange={v => onChange(key, v)} />
      ))}
    </div>
  );
}
function ProfileRow({ icon, title, detail, isLast, danger, onTap }) {
  return (
    <div
      role={onTap ? 'button' : undefined}
      tabIndex={onTap ? 0 : undefined}
      onClick={onTap}
      onKeyDown={event => {
        if (!onTap) return;
        if (event.key === 'Enter' || event.key === ' ') {
          event.preventDefault();
          onTap();
        }
      }}
      style={{
        display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px',
        borderBottom: isLast ? 'none' : '0.5px solid var(--border)',
        cursor: onTap ? 'pointer' : 'default',
        color: danger ? 'var(--danger)' : 'var(--ink)',
      }}
    >
      <div style={{ color: danger ? 'var(--danger)' : 'var(--ink-muted)', display: 'flex' }}>{icon}</div>
      <div style={{ flex: 1, fontSize: 14, fontWeight: 500 }}>{title}</div>
      {detail && <div style={{ fontSize: 13, color: 'var(--ink-muted)' }}>{detail}</div>}
      {onTap && <I.chevR style={{ color: 'var(--ink-faint)', width: 18, height: 18 }} />}
    </div>
  );
}

// ─── ADMIN JOB MONITOR ────────────────────────────────────────────────
function AdminScreen({ ctx }) {
  const { back, admin, reloadAdmin, user } = ctx;
  const [jobs, setJobs] = React.useState(admin?.jobs || []);
  const [debug, setDebug] = React.useState(true);

  React.useEffect(() => {
    setJobs(admin?.jobs || []);
  }, [admin]);

  React.useEffect(() => {
    if (user?.isAdmin) reloadAdmin().catch(() => {});
  }, [user?.isAdmin]);

  if (!user?.isAdmin) {
    return (
      <div style={{ height: '100%', background: 'var(--bg)' }}>
        <TopBar title="Job-Monitor" onBack={back} />
        <EmptyState icon={<I.shield />} title="Adminbereich" subtitle="Dieser Bereich ist nur für Admin-Konten sichtbar." />
      </div>
    );
  }

  // Animate running jobs
  React.useEffect(() => {
    const t = setInterval(() => {
      setJobs(js => js.map(j => {
        if (j.status === 'running' && j.progress < 100) {
          const newP = Math.min(100, j.progress + Math.random() * 3);
          return { ...j, progress: newP };
        }
        return j;
      }));
    }, 800);
    return () => clearInterval(t);
  }, []);

  const counts = {
    running: jobs.filter(j => j.status === 'running').length,
    queued: jobs.filter(j => j.status === 'queued').length,
    completed: jobs.filter(j => j.status === 'completed').length,
    failed: jobs.filter(j => j.status === 'failed' || j.status === 'skipped').length,
  };

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg)' }}>
      <TopBar title="Job-Monitor" onBack={back} trailing={
        <span className="chip" style={{
          background: debug ? 'var(--ink)' : 'var(--surface-2)',
          color: debug ? '#fff' : 'var(--ink-muted)',
          fontSize: 11, padding: '5px 10px', cursor: 'pointer',
        }} onClick={() => setDebug(!debug)}>DEBUG {debug ? 'ON' : 'OFF'}</span>
      } />
      <div className="phone-scroll" style={{ flex: 1, padding: '12px 16px 100px' }}>
        {/* Stat strip */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 8, marginBottom: 16 }}>
          <MiniStat label="Laufend" value={counts.running} color="#2A6FDB" />
          <MiniStat label="Warten" value={counts.queued} color="#C28428" />
          <MiniStat label="Fertig" value={counts.completed} color="#2F8F5A" />
          <MiniStat label="Fehler" value={counts.failed} color="#C8331C" />
        </div>

        {/* Job list */}
        <h3 className="section-title" style={{ marginBottom: 10 }}>Aktive & geplante Jobs</h3>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {jobs.map(j => <JobRow key={j.id} job={j} />)}
        </div>

        {/* Debug panel */}
        {debug && (
          <div style={{ marginTop: 24 }}>
            <h3 className="section-title" style={{ marginBottom: 10 }}>Debug-Konsole</h3>
            <div style={{
              background: '#15110C', color: '#A9D2B5', padding: 14, borderRadius: 12,
              fontFamily: 'var(--font-mono)', fontSize: 11, lineHeight: 1.6,
              maxHeight: 220, overflowY: 'auto',
            }}>
              {(admin?.audits || []).length === 0 ? (
                <div>Keine aktuellen Audit-Eintraege.</div>
              ) : (
                admin.audits.map(a => (
                  <div key={a.id} style={{ marginBottom: 8 }}>
                    <div style={{ color: '#5B7B66' }}>[{fmtDateTime(a.created_at)}] {a.type}</div>
                    <div style={{ color: a.need_attention === 'Y' ? '#E07C74' : '#A9D2B5' }}>{a.message}</div>
                  </div>
                ))
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
function MiniStat({ label, value, color }) {
  return (
    <div className="card" style={{ padding: '10px 8px', textAlign: 'center' }}>
      <div style={{ fontSize: 22, fontWeight: 700, color, letterSpacing: -0.02, fontVariantNumeric: 'tabular-nums' }}>{value}</div>
      <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--ink-muted)', textTransform: 'uppercase', letterSpacing: 0.04, marginTop: 2 }}>{label}</div>
    </div>
  );
}
function JobRow({ job }) {
  const statusCfg = {
    running:   { c: '#2A6FDB', bg: 'var(--info-soft)',    label: 'läuft' },
    queued:    { c: '#C28428', bg: 'var(--warn-soft)',    label: 'wartet' },
    completed: { c: '#2F8F5A', bg: 'var(--success-soft)', label: 'fertig' },
    failed:    { c: '#C8331C', bg: 'var(--danger-soft)',  label: 'fehler' },
    skipped:   { c: '#6B6259', bg: 'var(--surface-2)',    label: 'übersprungen' },
  };
  const cfg = statusCfg[job.status];
  const kindIcon = job.kind === 'ai-eval' ? <I.spark /> : <I.refresh />;
  return (
    <div className="card" style={{ padding: 12 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
        <div style={{ width: 32, height: 32, borderRadius: 9, background: cfg.bg, color: cfg.c, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
          {kindIcon}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)' }}>
              {job.kind === 'ai-eval' ? 'KI-Eval' : 'Scrape'} · {job.target}
            </div>
            <span className="chip" style={{ background: cfg.bg, color: cfg.c, fontSize: 10, padding: '2px 8px' }}>{cfg.label}</span>
          </div>
          <div style={{ fontSize: 11, color: 'var(--ink-muted)', marginTop: 2 }}>
            {job.search} · {job.items}
          </div>
          {job.status === 'running' && (
            <div style={{ marginTop: 8, height: 4, background: 'var(--surface-2)', borderRadius: 999, overflow: 'hidden' }}>
              <div style={{ width: `${job.progress}%`, height: '100%', background: cfg.c, borderRadius: 999, transition: 'width .8s ease' }} />
            </div>
          )}
          {job.error && (
            <div style={{ fontSize: 11, color: 'var(--danger)', marginTop: 6, fontFamily: 'var(--font-mono)' }}>
              {job.error}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  MietenDashboardScreen, SwipeScreen, PortfolioScreen, NotificationsScreen, ProfileScreen, AdminScreen,
});
