/* ============================================================
   Collaborator modes — Editor "Edit mode" & Reviewer "Review mode".
   When an editor or reviewer enters their mode, the public domain
   pages are replaced by a focused dashboard (ModeHome) that lists
   only the sections they can act on, each with a notification-style
   count of items waiting for them. Plus the shared-pages index and
   the admin "Manage roles & shared pages" modal.
   ============================================================ */
const { useState: uSm, useMemo: uMm } = React;

const MT = {
  en: {
    editHi: "Edit workspace", reviewHi: "Review workspace", publishHi: "Publish workspace", testerHi: "Preview workspace",
    editSub: "Pick a section to work on. Badges show drafts waiting to be finished or sent for review.",
    reviewSub: "Pick a section to review. Badges show pieces an editor has sent for your approval.",
    publishSub: "Pick a section to publish. Badges show pieces a reviewer has validated and that are ready to go live.",
    testerSub: "Pick a section to preview. Badges show pre-released pieces (in review or validated) you can try before they go live.",
    toEdit: "to edit", toReview: "to review", toPublish: "to publish", toPreview: "to preview", nothing: "all clear",
    sections: "Sections", other: "Other", shared: "Content shared with me", seeShared: "See all my shared content",
    open: "Open", reviewMode: "Reviewer mode", editMode: "Edit mode", noShared: "No pages are shared with you yet.",
    back: "Back to site", privateTag: "private",
  },
  fr: {
    editHi: "Espace d'\u00e9dition", reviewHi: "Espace de relecture", publishHi: "Espace de publication", testerHi: "Espace d'aper\u00e7u",
    editSub: "Choisissez une section. Les badges indiquent les brouillons \u00e0 finir ou \u00e0 envoyer en relecture.",
    reviewSub: "Choisissez une section \u00e0 relire. Les badges indiquent les contenus qu'un \u00e9diteur vous a envoy\u00e9s.",
    publishSub: "Choisissez une section \u00e0 publier. Les badges indiquent les contenus valid\u00e9s, pr\u00eats \u00e0 \u00eatre mis en ligne.",
    testerSub: "Choisissez une section \u00e0 pr\u00e9visualiser. Les badges indiquent les contenus en pr\u00e9-sortie (en relecture ou valid\u00e9s).",
    toEdit: "\u00e0 \u00e9diter", toReview: "\u00e0 relire", toPublish: "\u00e0 publier", toPreview: "\u00e0 voir", nothing: "rien \u00e0 faire",
    sections: "Sections", other: "Other", shared: "Contenus partag\u00e9s avec moi", seeShared: "Voir tous mes contenus partag\u00e9s",
    open: "Ouvrir", reviewMode: "Mode relecture", editMode: "Mode \u00e9dition", noShared: "Aucune page ne vous est partag\u00e9e pour l'instant.",
    back: "Retour au site", privateTag: "priv\u00e9e",
  },
};
function useMT() { const { lang } = useNav(); return MT[lang] || MT.en; }

function iconForKind(k) { return k === "video" ? "play" : k === "podcast" ? "msg" : "edit"; }

/* count of pieces in a section actionable in this mode's status(es) — per PIECE
   (any language), matching the section-list pool exactly so the badge never
   disagrees with what's inside. Private items need a grant (editors/reviewers)
   and never count for publishers / testers. The hidden template counts like any
   other draft. */
function modeCount(db, kind, status, session, role) {
  return (db.content || []).filter(c => c.type === kind && itemActionable(db, c, status, session, role, false)).length;
}
function otherModeCount(db, status, session, role) {
  return (db.otherPages || []).filter(p => p.kind !== "secret" && itemActionable(db, p, status, session, role, false)).length;
}

/* ===================== MODE HOME (editor / reviewer dashboard) ===================== */
function ModeHome() {
  const { db } = useStore();
  const { go, lang, session, reviewMode, publishMode, testerMode, role } = useNav();
  const t = useMT();
  const mode = publishMode ? "publish" : testerMode ? "tester" : reviewMode ? "review" : "edit";
  const status = mode === "review" ? "review" : mode === "publish" ? "validated" : mode === "tester" ? ["review", "validated"] : "draft";
  const verb = mode === "review" ? t.toReview : mode === "publish" ? t.toPublish : mode === "tester" ? t.toPreview : t.toEdit;
  const hi = mode === "review" ? t.reviewHi : mode === "publish" ? t.publishHi : mode === "tester" ? t.testerHi : t.editHi;
  const sub = mode === "review" ? t.reviewSub : mode === "publish" ? t.publishSub : mode === "tester" ? t.testerSub : t.editSub;
  const accent = roleMeta(role).color;

  // Only sections this role can act on (Permissions_v2): public sections by default,
  // hidden sections only when granted editorially. "Other" only with an Other-page grant.
  const visibleSections = db.sections.filter(s => sectionEditorialAccess(db, s, session, role));
  const otherAccessible = role === "admin" || (db.otherPages || []).some(p => p.kind !== "secret" && hasEditorialAccess(db, p, session, role));
  const cards = [
    ...visibleSections.map(s => ({
      key: s.id, label: secLabel(s, lang), icon: iconForKind(s.kind), logo: s.logo,
      count: modeCount(db, s.kind, status, session, role), route: s.route,
    })),
    ...(otherAccessible ? [{ key: "other", label: t.other, icon: "compass", logo: null, count: otherModeCount(db, status, session, role), route: "/other" }] : []),
  ];

  return (
    <div className="mode-home" style={{ "--mc": accent }}>
      <window.ModeTopBar />
      <div className="mh-wrap">
        <div className="mh-hero">
          <div className="mh-kicker">{hi}</div>
          <h1 className="mh-title">{lang === "fr" ? "Bonjour" : "Hi"}, {session ? session.first : ""}<span className="mh-dot">.</span></h1>
          <p className="mh-sub">{sub}</p>
        </div>

        <div className="mh-caphead"><span className="mono">{t.sections.toUpperCase()}</span><hr className="grow sep" /></div>
        <div className="mh-grid">
          {cards.map(c => (
            <button key={c.key} className={"mh-card" + (c.count > 0 ? " hot" : "")} onClick={() => go(c.route)}>
              <span className="mh-card-ic">
                {c.logo ? <img src={c.logo} alt="" /> : <Icon name={c.icon} size={26} />}
                {c.count > 0 && <span className="mh-badge">{c.count}</span>}
              </span>
              <span className="mh-card-l">{c.label}</span>
              <span className="mh-card-c">{c.count > 0 ? `${c.count} ${verb}` : t.nothing}</span>
              <span className="mh-card-go"><Icon name="arrow" size={18} /></span>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* compact top bar for mode pages — brand + lang + menu + identity (always present) */
function ModeTopBar() {
  const { db } = useStore();
  const { go, lang, setLang } = useNav();
  const [menuOpen, setMenuOpen] = uSm(false);
  const p = db.profile;
  const homeDomain = db.domains.find(d => d.route === p.defaultRoute) || db.domains[0];
  return (
    <>
      <header className="topbar" style={{ position: "static" }}>
        <div className="brand-wrap">
          <a className="brand" onClick={() => go(p.defaultRoute)} style={{ cursor: "pointer" }}>
            <span className="b1">{p.first}</span><span className="b2">{p.last}<span className="dot">.</span></span>
          </a>
        </div>
        <div className="topright">
          <div className="lang">
            <button className={lang === "en" ? "on" : ""} onClick={() => setLang("en")}>EN</button>
            <button className={lang === "fr" ? "on" : ""} onClick={() => setLang("fr")}>FR</button>
          </div>
          <button className="menubtn" onClick={() => setMenuOpen(true)} aria-label="menu"><Icon name="menu" size={24} /></button>
          <IdentityControl />
        </div>
      </header>
      <MenuPanel open={menuOpen} onClose={() => setMenuOpen(false)} domain={homeDomain} editMode={false} goWindow={(n) => { setMenuOpen(false); go(p.defaultRoute); }} />
    </>
  );
}

/* group a user's content/page grants (not whole-section grants) by the section they
   come from. Returns [{ key, label, logo, kind, items }] — one entry per section. */
function sharedSectionGroups(db, session, lang) {
  const grants = userGrantsRanked(db, session).filter(g => g.kind !== "section");
  const groups = [];
  grants.forEach(g => {
    const key = g.sectionId || "other";
    let grp = groups.find(x => x.key === key);
    if (!grp) {
      const sec = (db.sections || []).find(s => s.id === g.sectionId);
      const label = sec ? secLabel(sec, lang) : (g.sectionLabel || "Other");
      grp = { key, label, logo: sec ? sec.logo : (g.logo || null), kind: sec ? sec.kind : g.sectionKind, items: [] };
      groups.push(grp);
    }
    grp.items.push(g);
  });
  return groups;
}

/* ===================== SHARED PAGES INDEX (guest / reviewer / tester / editor) =====================
   Mirrors the public site: the shared content is presented as the SECTIONS it lives in
   (Blog, Videos, Other…), exactly like the public section tabs. Opening one lands on a
   "<Section> — shared" page that lists only the pieces shared with this user. */
function SharedPagesIndex() {
  const { db } = useStore();
  const { go, lang, session, role, prevPath } = useNav();
  const groups = sharedSectionGroups(db, session, lang);
  const fr = lang === "fr";
  const title = fr ? "Contenus partag\u00e9s" : "Shared content";
  const sub = fr
    ? "Les sections qui contiennent des contenus partag\u00e9s avec vous. Ouvrez-en une pour voir uniquement ce qui vous est partag\u00e9."
    : "The sections that hold content shared with you. Open one to see only what's been shared with you.";
  const home = db.profile.defaultRoute;
  const back = { label: fr ? "Retour" : "Back", to: () => { if (prevPath && prevPath !== "/shared") go(prevPath); else if (window.history.length > 1) window.history.back(); else go(home); } };
  const grantIcon = (k) => k === "video" ? "play" : k === "podcast" ? "msg" : k === "secret" ? "lock" : "edit";
  return (
    <div>
      <window.SectionHeader back={back} />
      <div className="section-wrap" style={{ maxWidth: 880 }}>
        <div className="section-head" style={{ margin: "30px 0 22px" }}>
          <div>
            <div className="mono dim" style={{ fontSize: 12, letterSpacing: ".14em", marginBottom: 8 }}>{fr ? "PARTAG\u00c9 AVEC VOUS" : "SHARED WITH YOU"} · {(roleMeta(role).label || "").toUpperCase()}</div>
            <h1 className="shared-title" style={{ fontSize: "clamp(30px,4.5vw,50px)", lineHeight: 1.12 }}><Scribble>{title}</Scribble></h1>
          </div>
        </div>
        <p className="dim" style={{ marginTop: 0, marginBottom: 22, maxWidth: 560 }}>{sub}</p>
        {groups.length ? (
          <div className="content-grid">
            {groups.map(grp => (
              <a key={grp.key} className="ccard" style={{ padding: 20, gap: 12 }} onClick={() => go("/shared/" + grp.key)}>
                <div className="row gap-12" style={{ alignItems: "center" }}>
                  <span className="shared-logo" style={{ width: 44, height: 44 }}>
                    {grp.logo ? <img src={grp.logo} alt="" /> : <Icon name={grantIcon(grp.kind)} size={22} />}
                  </span>
                  <div className="col" style={{ gap: 2 }}>
                    <span style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 20, lineHeight: 1.1 }}>{grp.label}</span>
                    <span className="mono dim" style={{ fontSize: 12 }}>{grp.items.length} {grp.items.length > 1 ? (fr ? "contenus partag\u00e9s" : "shared items") : (fr ? "contenu partag\u00e9" : "shared item")}</span>
                  </div>
                </div>
                <div className="row gap-8" style={{ color: "var(--accent-ink)", fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 13, marginTop: "auto" }}>{fr ? "Ouvrir" : "Open"} <Icon name="arrow" size={14} /></div>
              </a>
            ))}
          </div>
        ) : (
          <div className="surface" style={{ padding: 40, textAlign: "center", color: "var(--muted)", marginTop: 22 }}>
            {fr ? "Aucun contenu ne vous est partag\u00e9 pour l'instant." : "No content is shared with you yet."}
          </div>
        )}
      </div>
    </div>
  );
}

/* ===================== SHARED SECTION PAGE ("<Section> — shared") =====================
   Reached from the shared index. Lists ONLY the pieces shared with this user that live
   in one section, with a "<Section> — shared" title. */
function SharedSectionPage({ sectionId }) {
  const { db } = useStore();
  const { go, lang, session, role } = useNav();
  const fr = lang === "fr";
  const groups = sharedSectionGroups(db, session, lang);
  const grp = groups.find(g => g.key === sectionId);
  const back = { label: fr ? "Contenus partag\u00e9s" : "Shared content", to: () => go("/shared") };
  const grantIcon = (k) => k === "video" ? "play" : k === "secret" ? "lock" : k === "section" ? "compass" : "edit";
  const sharedWord = fr ? "partag\u00e9" : "shared";
  const secName = grp ? grp.label : (fr ? "Section" : "Section");
  return (
    <div>
      <window.SectionHeader back={back} />
      <div className="section-wrap" style={{ maxWidth: 880 }}>
        <div className="section-head" style={{ margin: "30px 0 22px" }}>
          <div>
            <div className="mono dim" style={{ fontSize: 12, letterSpacing: ".14em", marginBottom: 8 }}>{fr ? "PARTAG\u00c9 AVEC VOUS" : "SHARED WITH YOU"} · {(roleMeta(role).label || "").toUpperCase()}</div>
            <h1 className="shared-title" style={{ fontSize: "clamp(30px,4.5vw,50px)", lineHeight: 1.12 }}><Scribble>{secName} — {sharedWord}</Scribble></h1>
          </div>
        </div>
        {grp && grp.items.length ? (
          <div className="content-grid" style={{ marginTop: 8 }}>
            {grp.items.map(g => (
              <a key={g.id} className="ccard" style={{ padding: 18, gap: 10 }} onClick={() => go(g.route)}>
                <div className="row gap-8" style={{ alignItems: "center" }}>
                  <span className="shared-logo">
                    {g.cover ? <img src={g.cover} alt="" /> : g.logo ? <img src={g.logo} alt="" /> : <Icon name={grantIcon(g.kind)} size={17} />}
                  </span>
                  <span style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 18, lineHeight: 1.15 }}>{g.label}</span>
                </div>
                {g.desc && <div className="cc-desc">{g.desc}</div>}
                <div className="row gap-8" style={{ alignItems: "center", marginTop: "auto" }}>
                  {g.privateItem && <span className="ml-edit-tag">{fr ? "priv\u00e9" : "private"}</span>}
                  <span className="grow" />
                  <span className="row gap-8" style={{ color: "var(--accent-ink)", fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 13 }}>{fr ? "Ouvrir" : "Open"} <Icon name="arrow" size={14} /></span>
                </div>
              </a>
            ))}
          </div>
        ) : (
          <div className="surface" style={{ padding: 40, textAlign: "center", color: "var(--muted)", marginTop: 22 }}>
            {fr ? "Aucun contenu ne vous est partag\u00e9 dans cette section." : "No content is shared with you in this section."}
          </div>
        )}
      </div>
    </div>
  );
}

/* ===================== MANAGE ROLES & SHARED PAGES (admin, in edit mode) ===================== */
function ManageAccessModal({ onClose }) {
  const { db, update } = useStore();
  const [userModal, setUserModal] = uSm(null);
  const A = window.Avatar, RB = window.RoleBadge, UM = window.UserModal;
  const secByKind = (k) => db.sections.find(s => s.kind === k);
  const labelOf = (c) => { const w = wholeLang(c, "en"); return w.title || c.ref; };
  const pageLabelOf = (p) => { const w = pageWholeLang(p, "en"); return w.label || p.id; };
  // rich, grouped target catalogue for the access picker (whole-language labels + per-lang status)
  const grantTargets = {
    sections: db.sections.map(s => ({ id: s.id, label: secLabel(s, "en") || s.label, kind: s.kind, hidden: !s.inMenu })),
    content: db.content.filter(c => c.ref !== "template-toolkit").map(c => ({
      id: c.id, label: labelOf(c), kind: c.type,
      sectionId: (secByKind(c.type) || {}).id || null,
      group: c.type === "video" ? "Videos" : "Articles",
      private: !!c.private,
      published: ["en", "fr"].some(lg => publishedInLang(c, lg)),
      status: langStatusSummary(c),
    })),
    pages: (db.otherPages || []).map(pg => ({
      id: pg.id, label: pageLabelOf(pg), kind: pg.kind,
      private: pg.published === false,
      published: ["en", "fr"].some(lg => statusOfLang(pg, lg) === "published"),
      status: langStatusSummary(pg),
    })),
  };
  const saveUser = (u) => {
    update(d => {
      d.users = d.users || [];
      if (userModal.mode === "add") d.users.push({ ...u, id: uid("u") });
      else { const i = d.users.findIndex(x => x.id === u.id); if (i >= 0) d.users[i] = u; }
    });
    setUserModal(null);
  };
  const delUser = (id) => update(d => { d.users = (d.users || []).filter(u => u.id !== id); });
  return (
    <>
      <Modal size="xl" title="Manage roles & shared content" onClose={onClose}
        footer={<><button className="btn ghost" onClick={onClose}>Close</button>
          <button className="btn accent" onClick={() => setUserModal({ mode: "add", user: { name: "", first: "", email: "", role: "reviewer", color: "#7a4fe0", pass: "", grants: [], editGrants: [] } })}><Icon name="plus" size={16} /> Invite a user</button></>}>
        <p className="dim" style={{ fontSize: 13, marginTop: -4 }}>Create a user by email, assign a role, and share private or unpublished content with them — without leaving edit mode.</p>
        <div className="user-rows" style={{ marginTop: 6 }}>
          {(db.users || []).map(u => {
            const grants = userGrants(db, u);
            return (
              <div key={u.id} className="user-row">
                {A && <A user={u} size={34} />}
                <div className="ur-id">
                  <div className="ur-name">{u.name}</div>
                  <div className="ur-mail mono">{u.email}</div>
                </div>
                {RB && <RB role={u.role} />}
                <div className="ur-grants">
                  {u.role === "admin"
                    ? <span className="ur-all">All content &amp; settings</span>
                    : (grants.length ? grants.map(g => <span key={g.id} className="ur-grant">{g.label}</span>) : <span className="dim" style={{ fontSize: 12 }}>no content shared</span>)}
                </div>
                <button className="btn ghost sm" onClick={() => setUserModal({ mode: "edit", user: JSON.parse(JSON.stringify(u)) })}><Icon name="edit" size={14} /> Manage</button>
              </div>
            );
          })}
        </div>
      </Modal>
      {userModal && UM && <UM data={userModal} targets={grantTargets} onClose={() => setUserModal(null)} onSave={saveUser} onDelete={delUser} />}
    </>
  );
}

Object.assign(window, { ModeHome, ModeTopBar, SharedPagesIndex, SharedSectionPage, ManageAccessModal, useMT });
