/* global React, window, Icon, Mascot, useT, useEyad,
   PORTAL_USER, PORTAL_SESSIONS, PORTAL_PROGRESS, PORTAL_BADGES,
   PORTAL_CERTS, PORTAL_LEADERS, PORTAL_REPORTS, PORTAL_INSIGHTS_AR, PORTAL_INSIGHTS_EN,
   SUBJECTS, ThemeIcon, CourseCover, TeacherPortrait */

// Eyad Academy — Student portal shell + Dashboard + Sessions views

const { useState, useEffect, useMemo, useRef } = React;

// ─────────────────────────────────────────────────────────────
// Utilities
// ─────────────────────────────────────────────────────────────
function pickName(rec, lang) {
  if (rec && typeof rec === "object" && "ar" in rec && "en" in rec) return rec[lang];
  return rec;
}
function subjectOf(id) { return (window.SUBJECTS || []).find(s => s.id === id) || {}; }
function subjectAccent(id) {
  return ({
    quran: "#8B7AD9", arabic: "#D9A441", math: "#6FA8DC", science: "#E89B8B",
  })[id] || "#D9A441";
}
function formatHourLabel(h, lang) {
  // h is 24-hr int — show "5:00 م" or "5:00 PM"
  const period = h >= 12 ? (lang === "ar" ? "م" : "PM") : (lang === "ar" ? "ص" : "AM");
  const hh = ((h + 11) % 12) + 1;
  return `${hh}:00 ${period}`;
}
function daysFromNowLabel(offset, lang) {
  if (offset === 0) return lang === "ar" ? "اليوم" : "Today";
  if (offset === 1) return lang === "ar" ? "غدًا" : "Tomorrow";
  if (offset === -1) return lang === "ar" ? "أمس" : "Yesterday";
  if (offset > 0) return (lang === "ar" ? "بعد " : "in ") + offset + (lang === "ar" ? " أيام" : " days");
  return (lang === "ar" ? "قبل " : "") + Math.abs(offset) + (lang === "ar" ? " أيام" : " days ago");
}
function greetingKey() {
  const h = new Date().getHours();
  if (h < 12) return "morning";
  if (h < 18) return "afternoon";
  return "evening";
}

// ─────────────────────────────────────────────────────────────
// PORTAL SHELL
// ─────────────────────────────────────────────────────────────
function Portal({ onExitToSite, onLogout }) {
  const t = useT();
  const { lang, theme, setLang, setTheme } = useEyad();
  const [view, setView] = useState("dashboard"); // current view key
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
  const [openSession, setOpenSession] = useState(null);
  const [logoutConfirm, setLogoutConfirm] = useState(false);

  // Esc closes mobile nav / session detail
  useEffect(() => {
    const onKey = (e) => {
      if (e.key !== "Escape") return;
      if (openSession) setOpenSession(null);
      else if (mobileNavOpen) setMobileNavOpen(false);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [mobileNavOpen, openSession]);

  const navItems = [
    { id: "dashboard",    icon: "dashIcon",  label: t.portal.nav.dashboard },
    { id: "sessions",     icon: "playIcon",  label: t.portal.nav.sessions },
    { id: "timetable",    icon: "calIcon",   label: t.portal.nav.timetable },
    { id: "progress",     icon: "chartIcon", label: t.portal.nav.progress },
    { id: "certificates", icon: "certIcon",  label: t.portal.nav.certificates },
    { id: "gamification", icon: "starIcon",  label: t.portal.nav.gamification },
    { id: "reports",      icon: "reportIcon", label: t.portal.nav.reports },
    { id: "settings",     icon: "cogIcon",   label: t.portal.nav.settings },
  ];

  const goView = (v) => { setView(v); setMobileNavOpen(false); window.scrollTo({ top: 0, behavior: "smooth" }); };

  return (
    <div className="portal">
      {mobileNavOpen && <div className="portal-scrim" onClick={() => setMobileNavOpen(false)}/>}
      <aside className={`portal-side ${mobileNavOpen ? "open" : ""}`}>
        <a href="#" className="portal-brand" onClick={(e) => { e.preventDefault(); goView("dashboard"); }}>
          <span className="brand-mark"><Icon name="spark" size={20}/></span>
          <span>{t.nav.brand}</span>
        </a>

        <div className="portal-user">
          <div className="portal-user-av" style={{ background: PORTAL_USER.avatarBg }}>{PORTAL_USER.avatar}</div>
          <div className="portal-user-info">
            <div className="portal-user-name">{pickName(PORTAL_USER.name, lang)}</div>
            <div className="portal-user-meta">{pickName(PORTAL_USER.grade, lang)}</div>
          </div>
        </div>

        <nav className="portal-nav">
          {navItems.map(item => (
            <button key={item.id}
              className={`portal-nav-item ${view === item.id ? "active" : ""}`}
              onClick={() => goView(item.id)}>
              <PortalIcon name={item.icon}/>
              <span>{item.label}</span>
            </button>
          ))}
        </nav>

        <div className="portal-side-foot">
          <button className="portal-nav-item" onClick={onExitToSite}>
            <PortalIcon name="homeIcon"/>
            <span>{t.portal.nav.backsite}</span>
          </button>
          <button className="portal-nav-item portal-nav-logout" onClick={() => setLogoutConfirm(true)}>
            <PortalIcon name="logoutIcon"/>
            <span>{t.portal.nav.logout}</span>
          </button>
        </div>
      </aside>

      <main className="portal-main">
        <header className="portal-top">
          <button className="portal-menu-btn" onClick={() => setMobileNavOpen(true)} aria-label="menu">
            <Icon name="menu" size={20}/>
          </button>
          <div className="portal-search">
            <SearchIcon/>
            <input placeholder={t.portal.topbar.search}/>
          </div>
          <div className="portal-top-actions">
            <button className="portal-icon-btn" onClick={() => setLang(lang === "ar" ? "en" : "ar")} aria-label="language">
              <span style={{ fontFamily: "var(--f-display)", fontWeight: 700, fontSize: 12 }}>{lang === "ar" ? "EN" : "ع"}</span>
            </button>
            <button className="portal-icon-btn" onClick={() => setTheme(theme === "light" ? "dark" : "light")} aria-label="theme">
              <ThemeIcon theme={theme}/>
            </button>
            <button className="portal-icon-btn portal-bell" aria-label="notifications">
              <BellIcon/>
              <span className="portal-bell-dot"/>
            </button>
            <div className="portal-xp-pill">
              <span className="lvl">{t.portal.topbar.level} {PORTAL_USER.level}</span>
              <span className="xp">{PORTAL_USER.xp.toLocaleString()}</span>
            </div>
          </div>
        </header>

        <div className="portal-content">
          {view === "dashboard"    && <DashboardView onOpenSession={setOpenSession} onGo={goView}/>}
          {view === "sessions"     && <SessionsView onOpenSession={setOpenSession}/>}
          {view === "timetable"    && <window.TimetableView onOpenSession={setOpenSession}/>}
          {view === "progress"     && <window.ProgressView/>}
          {view === "certificates" && <window.CertificatesView/>}
          {view === "gamification" && <window.GamificationView/>}
          {view === "reports"      && <window.ReportsView/>}
          {view === "settings"     && <window.SettingsView/>}
        </div>
      </main>

      {openSession && <SessionDetailModal session={openSession} onClose={() => setOpenSession(null)}/>}
      {logoutConfirm && <LogoutConfirm onConfirm={onLogout} onCancel={() => setLogoutConfirm(false)}/>}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// DASHBOARD
// ─────────────────────────────────────────────────────────────
function DashboardView({ onOpenSession, onGo }) {
  const t = useT();
  const { lang } = useEyad();
  const greeting = t.portal.greeting[greetingKey()];
  const insights = lang === "ar" ? PORTAL_INSIGHTS_AR : PORTAL_INSIGHTS_EN;

  // Next session = upcoming with smallest dayOffset, else first
  const upcoming = PORTAL_SESSIONS
    .filter(s => s.dayOffset >= 0)
    .sort((a, b) => a.dayOffset - b.dayOffset || a.startHour - b.startHour);
  const next = upcoming[0];

  const todayTomorrow = upcoming.filter(s => s.dayOffset <= 1).slice(0, 4);

  return (
    <>
      <div className="portal-head">
        <div>
          <div className="portal-eyebrow">{greeting}</div>
          <h1 className="portal-h1">{pickName(PORTAL_USER.name, lang).split(" ")[0]} ✨</h1>
          <p className="portal-sub">{t.portal.dashboard.sub}</p>
        </div>
        <div className="portal-mascot-tile">
          <Mascot style="real"/>
        </div>
      </div>

      <div className="dash-grid">
        {/* Next session — featured */}
        {next && (
          <div className="dash-card dash-next">
            <NextSessionCard session={next} onOpen={onOpenSession}/>
          </div>
        )}

        {/* Streak */}
        <div className="dash-card dash-streak">
          <div className="dash-card-kicker">{t.portal.dashboard.streak.kicker}</div>
          <div className="streak-flame">
            <FlameIcon/>
            <div className="streak-num">{PORTAL_USER.streak}<span>{t.portal.dashboard.streak.days}</span></div>
          </div>
          <div className="dash-card-foot">{t.portal.dashboard.streak.motivate}</div>
        </div>

        {/* XP */}
        <div className="dash-card dash-xp">
          <div className="dash-card-kicker">{t.portal.dashboard.xp.kicker}</div>
          <div className="xp-level">
            <div className="xp-level-badge">{t.portal.dashboard.xp.level} {PORTAL_USER.level}</div>
            <div className="xp-level-num">{PORTAL_USER.xp.toLocaleString()}<span>/{PORTAL_USER.xpNext.toLocaleString()}</span></div>
          </div>
          <div className="xp-bar"><div style={{ width: `${(PORTAL_USER.xp / PORTAL_USER.xpNext) * 100}%` }}/></div>
          <div className="dash-card-foot">{(PORTAL_USER.xpNext - PORTAL_USER.xp).toLocaleString()} {t.portal.topbar.xp} {t.portal.dashboard.xp.next}</div>
        </div>

        {/* This week */}
        <div className="dash-card dash-week">
          <div className="dash-card-kicker">{t.portal.dashboard.week.kicker}</div>
          <div className="week-stat">
            <div className="week-stat-row"><span className="big">5</span> <span className="of">{t.portal.dashboard.week.attended} 5 {t.portal.dashboard.week.lessons}</span></div>
            <div className="week-stat-row"><span className="big">6.5</span> <span className="of">{t.portal.dashboard.week.h}</span></div>
          </div>
          <MiniSparkline data={PORTAL_PROGRESS.weeklyHours}/>
        </div>

        {/* Insights */}
        <div className="dash-card dash-insights">
          <div className="dash-card-kicker">{t.portal.dashboard.insights.h}</div>
          <ul className="insight-list">
            {insights.map((it, i) => (
              <li key={i} className={`insight insight-${it.tone}`}>
                <span className="insight-dot"/>
                <span>{it.text}</span>
              </li>
            ))}
          </ul>
        </div>

        {/* Upcoming list */}
        <div className="dash-card dash-upcoming">
          <div className="dash-card-head">
            <div className="dash-card-kicker">{t.portal.dashboard.upcoming.h}</div>
            <button className="dash-link" onClick={() => onGo("sessions")}>
              {t.portal.dashboard.progressGlance.viewAll} <Icon name="chevron" size={12}/>
            </button>
          </div>
          {todayTomorrow.length === 0
            ? <div className="dash-empty">{t.portal.dashboard.upcoming.empty}</div>
            : (
              <ul className="upcoming-list">
                {todayTomorrow.map((s) => (
                  <li key={s.id} onClick={() => onOpenSession(s)}>
                    <div className="upcoming-icon" style={{ background: subjectAccent(s.subject) + "33", color: subjectAccent(s.subject) }}>
                      <Icon name={subjectOf(s.subject).icon || "book"} size={18}/>
                    </div>
                    <div className="upcoming-info">
                      <div className="upcoming-title">{lang === "ar" ? s.titleAr : s.titleEn}</div>
                      <div className="upcoming-meta">
                        {daysFromNowLabel(s.dayOffset, lang)} · {formatHourLabel(s.startHour, lang)} · {pickName({ ar: s.teacher.name_ar, en: s.teacher.name_en }, lang)}
                      </div>
                    </div>
                    <Icon name="chevron" size={16}/>
                  </li>
                ))}
              </ul>
            )}
        </div>

        {/* Progress glance */}
        <div className="dash-card dash-progress">
          <div className="dash-card-head">
            <div className="dash-card-kicker">{t.portal.dashboard.progressGlance.h}</div>
            <button className="dash-link" onClick={() => onGo("progress")}>
              {t.portal.dashboard.progressGlance.viewAll} <Icon name="chevron" size={12}/>
            </button>
          </div>
          <ul className="glance-list">
            {PORTAL_PROGRESS.subjects.map((p) => {
              const subj = subjectOf(p.id);
              const pct = Math.round((p.completed / p.total) * 100);
              return (
                <li key={p.id}>
                  <div className="glance-icon" style={{ background: subj.glyph, color: "var(--always-navy)" }}>
                    <Icon name={subj.icon} size={16}/>
                  </div>
                  <div style={{ flex: 1 }}>
                    <div className="glance-row">
                      <span>{t.subjects.items[p.id]?.name}</span>
                      <span className="glance-pct">{pct}%</span>
                    </div>
                    <div className="glance-bar"><div style={{ width: `${pct}%`, background: p.accent }}/></div>
                  </div>
                </li>
              );
            })}
          </ul>
        </div>

        {/* Badges glance */}
        <div className="dash-card dash-badges">
          <div className="dash-card-head">
            <div className="dash-card-kicker">{t.portal.dashboard.badges.h}</div>
            <button className="dash-link" onClick={() => onGo("gamification")}>
              {t.portal.dashboard.badges.viewAll} <Icon name="chevron" size={12}/>
            </button>
          </div>
          <div className="badges-glance">
            {PORTAL_BADGES.filter(b => b.earned).slice(0, 4).map((b) => (
              <div key={b.id} className="badge-mini">
                <div className="badge-mini-glow" style={{ background: `radial-gradient(circle, ${b.glow}55, transparent 65%)` }}/>
                <div className="badge-mini-disc" style={{ background: `linear-gradient(135deg, ${b.glow}, ${b.glow}aa)` }}>
                  <Icon name={b.icon} size={22}/>
                </div>
                <div className="badge-mini-name">{lang === "ar" ? b.name_ar : b.name_en}</div>
              </div>
            ))}
          </div>
        </div>

        {/* Motivation */}
        <div className="dash-card dash-motivate">
          <div className="dash-card-kicker">{t.portal.dashboard.motivate.h}</div>
          <p>{t.portal.dashboard.motivate.body}</p>
        </div>
      </div>
    </>
  );
}

function NextSessionCard({ session, onOpen }) {
  const t = useT();
  const { lang } = useEyad();
  const subj = subjectOf(session.subject);
  const accent = subjectAccent(session.subject);
  const isNow = session.dayOffset === 0;
  return (
    <div className="next-session" style={{ "--accent": accent }}>
      <div className="next-session-cover">
        <CourseCover subject={session.subject}/>
      </div>
      <div className="next-session-info">
        <div className="dash-card-kicker" style={{ color: accent }}>{t.portal.dashboard.next.kicker}</div>
        <h2>{lang === "ar" ? session.titleAr : session.titleEn}</h2>
        <div className="next-session-meta">
          <span><Icon name="users" size={14}/> {t.portal.dashboard.next.with} {pickName({ ar: session.teacher.name_ar, en: session.teacher.name_en }, lang)}</span>
          <span className="dot"/>
          <span><Icon name="clock" size={14}/> {daysFromNowLabel(session.dayOffset, lang)} · {formatHourLabel(session.startHour, lang)}</span>
        </div>
        <div className="next-session-id">
          <span className="lbl">{t.portal.dashboard.next.meetingId}</span>
          <span className="val en">{session.zoomMeetingId}</span>
        </div>
        <div className="next-session-cta">
          <button className="btn btn-primary" onClick={() => onOpen(session)}>
            <ZoomGlyph/>
            {isNow ? t.portal.dashboard.next.now : t.portal.dashboard.next.join}
          </button>
          <button className="btn btn-ghost" onClick={() => onOpen(session)}>
            {t.portal.sessions.details}
            <Icon name="arrow" size={16}/>
          </button>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SESSIONS LIST
// ─────────────────────────────────────────────────────────────
function SessionsView({ onOpenSession }) {
  const t = useT();
  const { lang } = useEyad();
  const [tab, setTab] = useState("upcoming");
  const list = useMemo(() => PORTAL_SESSIONS
    .filter(s => tab === "upcoming" ? s.dayOffset >= 0 : s.dayOffset < 0)
    .sort((a, b) => tab === "upcoming"
      ? a.dayOffset - b.dayOffset || a.startHour - b.startHour
      : b.dayOffset - a.dayOffset),
    [tab]);

  return (
    <>
      <PageHead h={t.portal.sessions.h} sub={t.portal.sessions.sub}/>
      <div className="ps-tabs">
        <button className={`ps-tab ${tab === "upcoming" ? "active" : ""}`} onClick={() => setTab("upcoming")}>
          {t.portal.sessions.tabs.upcoming}
          <span className="count">{PORTAL_SESSIONS.filter(s => s.dayOffset >= 0).length}</span>
        </button>
        <button className={`ps-tab ${tab === "past" ? "active" : ""}`} onClick={() => setTab("past")}>
          {t.portal.sessions.tabs.past}
          <span className="count">{PORTAL_SESSIONS.filter(s => s.dayOffset < 0).length}</span>
        </button>
      </div>
      {list.length === 0
        ? <div className="ps-empty">{t.portal.sessions.empty[tab]}</div>
        : (
          <div className="sessions-list">
            {list.map((s) => (
              <SessionCard key={s.id} session={s} onOpen={onOpenSession}/>
            ))}
          </div>
        )}
    </>
  );
}

function SessionCard({ session, onOpen }) {
  const t = useT();
  const { lang } = useEyad();
  const accent = subjectAccent(session.subject);
  const subj = subjectOf(session.subject);
  const isUpcoming = session.dayOffset >= 0;
  return (
    <article className="session-card" onClick={() => onOpen(session)} style={{ "--accent": accent }}>
      <div className="session-card-stripe"/>
      <div className="session-card-icon" style={{ background: subj.glyph, color: "var(--always-navy)" }}>
        <Icon name={subj.icon || "book"} size={26}/>
      </div>
      <div className="session-card-body">
        <div className="session-card-sub" style={{ color: accent }}>{t.subjects.items[session.subject]?.name}</div>
        <h3>{lang === "ar" ? session.titleAr : session.titleEn}</h3>
        <div className="session-card-meta">
          <span><Icon name="users" size={13}/> {pickName({ ar: session.teacher.name_ar, en: session.teacher.name_en }, lang)}</span>
          <span><Icon name="clock" size={13}/> {daysFromNowLabel(session.dayOffset, lang)} · {formatHourLabel(session.startHour, lang)} · {session.durationMin} {lang === "ar" ? "د" : "min"}</span>
        </div>
      </div>
      <div className="session-card-action">
        {isUpcoming ? (
          <button className="btn btn-primary" onClick={(e) => { e.stopPropagation(); onOpen(session); }}>
            <ZoomGlyph small/>
            {t.portal.sessions.join}
          </button>
        ) : (
          <div className="session-card-grade">
            <span className="lbl">{t.portal.sessions.grade}</span>
            <span className="val">{lang === "ar" ? session.grade : session.grade_en || "—"}</span>
          </div>
        )}
      </div>
    </article>
  );
}

// ─────────────────────────────────────────────────────────────
// SESSION DETAIL MODAL — with Zoom join confirm + file upload
// ─────────────────────────────────────────────────────────────
function SessionDetailModal({ session, onClose }) {
  const t = useT();
  const { lang } = useEyad();
  const accent = subjectAccent(session.subject);
  const [confirmJoin, setConfirmJoin] = useState(false);
  const [files, setFiles] = useState(session.materials || []);
  const fileInputRef = useRef(null);

  useEffect(() => {
    document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = ""; };
  }, []);

  const onFileChosen = (e) => {
    const f = e.target.files?.[0]; if (!f) return;
    const ext = (f.name.split(".").pop() || "").toLowerCase();
    const kind = ["pdf"].includes(ext) ? "pdf"
              : ["mp3", "wav", "m4a"].includes(ext) ? "audio"
              : ["jpg", "jpeg", "png", "gif", "webp"].includes(ext) ? "image"
              : "file";
    const sizeMb = (f.size / (1024 * 1024)).toFixed(1) + " MB";
    setFiles([...files, { id: `up-${Date.now()}`, name_ar: f.name, name_en: f.name, kind, size: sizeMb, uploaded_by: "you" }]);
    e.target.value = "";
  };

  const removeFile = (id) => setFiles(files.filter(f => f.id !== id));

  return (
    <div className="portal-modal-overlay" onClick={onClose}>
      <div className="portal-modal" onClick={(e) => e.stopPropagation()} style={{ "--accent": accent }}>
        <div className="portal-modal-cover">
          <CourseCover subject={session.subject}/>
          <button className="modal-close" onClick={onClose}><Icon name="close" size={18}/></button>
          <div className="portal-modal-cover-text">
            <div className="kicker" style={{ color: "white", opacity: 0.85 }}>
              {t.subjects.items[session.subject]?.name} · {daysFromNowLabel(session.dayOffset, lang)} · {formatHourLabel(session.startHour, lang)}
            </div>
            <h2>{lang === "ar" ? session.titleAr : session.titleEn}</h2>
          </div>
        </div>
        <div className="portal-modal-body">
          <div className="pm-grid">
            <div className="pm-info">
              <div className="pm-row">
                <span className="pm-row-lbl">{t.portal.sessions.with}</span>
                <span className="pm-row-val">{pickName({ ar: session.teacher.name_ar, en: session.teacher.name_en }, lang)}</span>
              </div>
              <div className="pm-row">
                <span className="pm-row-lbl">{t.portal.sessions.time}</span>
                <span className="pm-row-val">{formatHourLabel(session.startHour, lang)} · {session.durationMin} {lang === "ar" ? "دقيقة" : "min"}</span>
              </div>
              <div className="pm-row">
                <span className="pm-row-lbl">{t.portal.sessions.date}</span>
                <span className="pm-row-val">{daysFromNowLabel(session.dayOffset, lang)}</span>
              </div>
              <div className="pm-row">
                <span className="pm-row-lbl">{t.portal.sessions.zoomId}</span>
                <span className="pm-row-val en">{session.zoomMeetingId}</span>
              </div>
              {session.status !== "completed" && (
                <button className="btn btn-primary pm-join" onClick={() => setConfirmJoin(true)}>
                  <ZoomGlyph/>
                  {t.portal.sessions.join}
                </button>
              )}
              {session.status === "completed" && (
                <div className="pm-grade">
                  <Icon name="check" size={18}/>
                  <span>{t.portal.sessions.grade}: <strong>{lang === "ar" ? session.grade : session.grade_en}</strong></span>
                </div>
              )}
            </div>
            <div className="pm-materials">
              <h4>{t.portal.sessions.materials}</h4>
              {files.length === 0 && <div className="pm-empty">{lang === "ar" ? "لا توجد ملفات بعد." : "No materials yet."}</div>}
              <ul className="pm-files">
                {files.map((f) => (
                  <li key={f.id}>
                    <FileTypeIcon kind={f.kind}/>
                    <div className="pm-file-meta">
                      <div className="pm-file-name">{lang === "ar" ? f.name_ar : f.name_en}</div>
                      <div className="pm-file-sub">{f.size} · {f.uploaded_by === "you" ? t.portal.sessions.uploadedYou : t.portal.sessions.uploadedTeacher}</div>
                    </div>
                    <div className="pm-file-actions">
                      <button className="pm-iconbtn" title={t.portal.sessions.download}><DownloadIcon/></button>
                      {f.uploaded_by === "you" && (
                        <button className="pm-iconbtn" onClick={() => removeFile(f.id)} title={t.portal.sessions.delete}><Icon name="close" size={14}/></button>
                      )}
                    </div>
                  </li>
                ))}
              </ul>
              <div className="pm-upload">
                <div className="pm-upload-hint">{t.portal.sessions.addHint}</div>
                <button className="btn btn-ghost" onClick={() => fileInputRef.current?.click()}>
                  <PaperclipIcon/>
                  {t.portal.sessions.upload}
                </button>
                <input type="file" hidden ref={fileInputRef} onChange={onFileChosen}/>
              </div>
            </div>
          </div>

          {session.notes_ar && session.notes_ar !== "—" && session.notes_ar !== "" && (
            <div className="pm-notes">
              <h4>{t.portal.sessions.notes}</h4>
              <p>{lang === "ar" ? session.notes_ar : session.notes_en}</p>
            </div>
          )}

          {session.status !== "completed" && (
            <div className="pm-chat">
              <h4>{t.portal.sessions.chat}</h4>
              <div className="pm-chat-empty">
                <ChatIcon/>
                <span>{t.portal.sessions.chatHint}</span>
              </div>
            </div>
          )}
        </div>
      </div>

      {confirmJoin && (
        <div className="zoom-confirm" onClick={(e) => e.stopPropagation()}>
          <div className="zoom-confirm-card">
            <ZoomBigIcon/>
            <h3>{t.portal.sessions.confirmJoin.h}</h3>
            <p>{t.portal.sessions.confirmJoin.body}</p>
            <div className="zoom-confirm-id en">{session.zoomMeetingId}</div>
            <div className="zoom-confirm-actions">
              <button className="btn btn-primary" onClick={() => { setConfirmJoin(false); window.open("https://zoom.us/j/" + session.zoomMeetingId.replace(/\s+/g, ""), "_blank", "noopener"); }}>
                <ZoomGlyph/>
                {t.portal.sessions.confirmJoin.btn}
              </button>
              <button className="btn btn-ghost" onClick={() => setConfirmJoin(false)}>{t.portal.sessions.confirmJoin.cancel}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// LOGOUT CONFIRM
// ─────────────────────────────────────────────────────────────
function LogoutConfirm({ onConfirm, onCancel }) {
  const t = useT();
  return (
    <div className="portal-modal-overlay" onClick={onCancel}>
      <div className="logout-modal" onClick={(e) => e.stopPropagation()}>
        <h3>{t.portal.logoutModal.h}</h3>
        <p>{t.portal.logoutModal.body}</p>
        <div className="logout-actions">
          <button className="btn btn-ghost" onClick={onCancel}>{t.portal.logoutModal.cancel}</button>
          <button className="btn btn-primary" onClick={onConfirm}>{t.portal.logoutModal.confirm}</button>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Shared atoms
// ─────────────────────────────────────────────────────────────
function PageHead({ h, sub }) {
  return (
    <div className="portal-head">
      <div>
        <h1 className="portal-h1">{h}</h1>
        <p className="portal-sub">{sub}</p>
      </div>
    </div>
  );
}

function MiniSparkline({ data }) {
  const max = Math.max(...data);
  const w = 220, hh = 56, pad = 4;
  const step = (w - pad * 2) / (data.length - 1);
  const pts = data.map((v, i) => [pad + i * step, pad + (1 - v / max) * (hh - pad * 2)]);
  const d = pts.map((p, i) => `${i === 0 ? "M" : "L"} ${p[0]} ${p[1]}`).join(" ");
  return (
    <svg viewBox={`0 0 ${w} ${hh}`} className="sparkline">
      <defs>
        <linearGradient id="spark-grad" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="var(--gold)" stopOpacity="0.4"/>
          <stop offset="100%" stopColor="var(--gold)" stopOpacity="0"/>
        </linearGradient>
      </defs>
      <path d={`${d} L ${pts[pts.length-1][0]} ${hh-pad} L ${pts[0][0]} ${hh-pad} Z`} fill="url(#spark-grad)"/>
      <path d={d} fill="none" stroke="var(--gold)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
      {pts.map((p, i) => <circle key={i} cx={p[0]} cy={p[1]} r="2.5" fill="var(--gold)"/>)}
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────
// Portal-specific icons
// ─────────────────────────────────────────────────────────────
function PortalIcon({ name }) {
  const s = { width: 18, height: 18, display: "inline-block", flexShrink: 0 };
  const sk = { fill: "none", stroke: "currentColor", strokeWidth: 1.7, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "dashIcon":   return <svg viewBox="0 0 24 24" style={s}><g {...sk}><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></g></svg>;
    case "playIcon":   return <svg viewBox="0 0 24 24" style={s}><g {...sk}><rect x="2" y="6" width="20" height="12" rx="2.5"/><path d="M10 9.5v5l4-2.5z" fill="currentColor" stroke="none"/></g></svg>;
    case "calIcon":    return <svg viewBox="0 0 24 24" style={s}><g {...sk}><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/></g></svg>;
    case "chartIcon":  return <svg viewBox="0 0 24 24" style={s}><g {...sk}><path d="M3 21h18"/><path d="M6 17v-5M10 17V9M14 17v-3M18 17V7"/></g></svg>;
    case "certIcon":   return <svg viewBox="0 0 24 24" style={s}><g {...sk}><circle cx="12" cy="10" r="5"/><path d="M9 14l-2 7 5-3 5 3-2-7"/></g></svg>;
    case "starIcon":   return <svg viewBox="0 0 24 24" style={s}><path d="M12 3l2.6 6 6.4.5-4.9 4.2 1.5 6.3L12 16.7 6.4 20l1.5-6.3L3 9.5l6.4-.5z" fill="currentColor"/></svg>;
    case "reportIcon": return <svg viewBox="0 0 24 24" style={s}><g {...sk}><path d="M6 3h9l5 5v13a1 1 0 01-1 1H6a1 1 0 01-1-1V4a1 1 0 011-1z"/><path d="M14 3v6h6M9 14h6M9 17h4"/></g></svg>;
    case "cogIcon":    return <svg viewBox="0 0 24 24" style={s}><g {...sk}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.6 1.6 0 00.3 1.7l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.6 1.6 0 00-1.7-.3 1.6 1.6 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.6 1.6 0 00-1-1.5 1.6 1.6 0 00-1.7.3l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.6 1.6 0 00.3-1.7 1.6 1.6 0 00-1.5-1H3a2 2 0 110-4h.1a1.6 1.6 0 001.5-1 1.6 1.6 0 00-.3-1.7l-.1-.1a2 2 0 112.8-2.8l.1.1a1.6 1.6 0 001.7.3h.1a1.6 1.6 0 001-1.5V3a2 2 0 114 0v.1a1.6 1.6 0 001 1.5 1.6 1.6 0 001.7-.3l.1-.1a2 2 0 112.8 2.8l-.1.1a1.6 1.6 0 00-.3 1.7v.1a1.6 1.6 0 001.5 1H21a2 2 0 110 4h-.1a1.6 1.6 0 00-1.5 1z"/></g></svg>;
    case "homeIcon":   return <svg viewBox="0 0 24 24" style={s}><g {...sk}><path d="M3 11l9-8 9 8M5 10v10a1 1 0 001 1h12a1 1 0 001-1V10"/></g></svg>;
    case "logoutIcon": return <svg viewBox="0 0 24 24" style={s}><g {...sk}><path d="M15 17l5-5-5-5M20 12H9M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/></g></svg>;
    default: return null;
  }
}

function SearchIcon() {
  return (<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>);
}
function BellIcon() {
  return (<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round"><path d="M6 8a6 6 0 1112 0c0 7 3 9 3 9H3s3-2 3-9z"/><path d="M10 21a2 2 0 004 0"/></svg>);
}
function FlameIcon() {
  return (
    <svg width="42" height="42" viewBox="0 0 64 64">
      <defs>
        <linearGradient id="flame-g" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="#F5D67A"/>
          <stop offset="60%" stopColor="#E8B954"/>
          <stop offset="100%" stopColor="#D9A441"/>
        </linearGradient>
      </defs>
      <path d="M32 6 C 22 16, 16 24, 16 36 C 16 48, 24 56, 32 56 C 40 56, 48 48, 48 36 C 48 28, 42 22, 38 28 C 40 20, 36 12, 32 6 Z" fill="url(#flame-g)"/>
      <path d="M32 22 C 28 28, 26 32, 26 38 C 26 44, 29 48, 32 48 C 35 48, 38 44, 38 38 C 38 34, 36 30, 32 22 Z" fill="#FFF6DC" opacity="0.8"/>
    </svg>
  );
}
function ZoomGlyph({ small = false }) {
  const sz = small ? 16 : 18;
  return (
    <svg width={sz} height={sz} viewBox="0 0 24 24" fill="currentColor">
      <rect x="2" y="6" width="14" height="12" rx="2"/>
      <path d="M22 17V7l-5 3v4z"/>
    </svg>
  );
}
function ZoomBigIcon() {
  return (
    <div style={{ width: 64, height: 64, margin: "0 auto 18px", borderRadius: 16, background: "linear-gradient(135deg, #2D8CFF, #1A5ED9)", display: "grid", placeItems: "center", boxShadow: "0 12px 28px rgba(45,140,255,0.4)" }}>
      <svg width="34" height="34" viewBox="0 0 24 24" fill="white">
        <rect x="2" y="6" width="14" height="12" rx="2"/>
        <path d="M22 17V7l-5 3v4z"/>
      </svg>
    </div>
  );
}
function DownloadIcon() {
  return (<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>);
}
function PaperclipIcon() {
  return (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M21 12.5l-9.2 9.2a5 5 0 11-7-7L14 5.5a3.3 3.3 0 014.7 4.7L9.4 19.5a1.7 1.7 0 11-2.4-2.4l8.4-8.4"/></svg>);
}
function ChatIcon() {
  return (<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 12a8 8 0 11-3.2-6.4L21 4l-1 4.4A8 8 0 0121 12z"/></svg>);
}
function FileTypeIcon({ kind }) {
  const bg = kind === "pdf" ? "#E89B8B" : kind === "audio" ? "#8B7AD9" : kind === "image" ? "#6FA8DC" : "#D9A441";
  const lbl = kind === "pdf" ? "PDF" : kind === "audio" ? "♪" : kind === "image" ? "IMG" : "FILE";
  return (
    <div className="pm-file-icon" style={{ background: bg }}>
      <span>{lbl}</span>
    </div>
  );
}

Object.assign(window, { Portal, DashboardView, SessionsView, SessionDetailModal, NextSessionCard,
  pickName, subjectOf, subjectAccent, formatHourLabel, daysFromNowLabel, PageHead });
