// Arcaid Guild — shared UI components

function GIcon({ name, size = 22 }) {
  const s = { width: size, height: size, display: "block", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    home: <><path d="M3 10.5L12 3l9 7.5" /><path d="M5 9.5V21h14V9.5" /></>,
    search: <><circle cx="11" cy="11" r="7" /><path d="M21 21l-4-4" /></>,
    column: <><rect x="3.5" y="4" width="17" height="16" rx="2.5" /><path d="M8 9h8M8 13h8M8 17h5" /></>,
    bell: <><path d="M6 9a6 6 0 1112 0c0 5 2 6 2 6H4s2-1 2-6z" /><path d="M10 20a2 2 0 004 0" /></>,
    more: <><circle cx="5" cy="12" r="1.6" /><circle cx="12" cy="12" r="1.6" /><circle cx="19" cy="12" r="1.6" /></>,
    plus: <><path d="M12 5v14M5 12h14" /></>,
    heart: <path d="M12 20s-7-4.4-7-9.3A3.8 3.8 0 0112 7a3.8 3.8 0 017 3.7C19 15.6 12 20 12 20z" />,
    bookmark: <path d="M6 4h12v16l-6-4-6 4z" />,
    comment: <path d="M21 12a8 8 0 01-11.5 7.2L4 20l.9-5A8 8 0 1121 12z" />,
    back: <path d="M15 5l-7 7 7 7" />,
    reply: <><path d="M9 7L4 12l5 5" /><path d="M4 12h9a6 6 0 016 6v1" /></>,
    pin: <><path d="M9 4h6l-1 6 3 3H7l3-3-1-6z" /><path d="M12 16v4" /></>,
    image: <><rect x="3.5" y="4.5" width="17" height="15" rx="2.5" /><circle cx="8.5" cy="9.5" r="1.6" /><path d="M5 18l5-5 4 3 3-3 4 4" /></>,
    eye: <><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z" /><circle cx="12" cy="12" r="3" /></>,
    link: <><path d="M9 15l6-6" /><path d="M11 7l1-1a3.5 3.5 0 015 5l-1 1" /><path d="M13 17l-1 1a3.5 3.5 0 01-5-5l1-1" /></>,
    check: <path d="M5 12l5 5L20 6" />,
    close: <path d="M6 6l12 12M18 6L6 18" />,
    send: <path d="M4 12l16-7-7 16-2-7-7-2z" />,
    car: <><path d="M4 13l1.5-4.5A2 2 0 017.4 7h9.2a2 2 0 011.9 1.5L20 13" /><path d="M3 13h18v4H3z" /><circle cx="7" cy="17.5" r="1.3" /><circle cx="17" cy="17.5" r="1.3" /></>,
    chevron: <path d="M9 6l6 6-6 6" />,
  };
  return <svg viewBox="0 0 24 24" style={s} aria-hidden="true">{paths[name]}</svg>;
}

function GAvatar({ handle, size = 40 }) {
  const u = GUILD_USERS[handle];
  if (!u) return null;
  return (
    <div className="g-avatar" style={{ width: size, height: size, background: u.avatar, fontSize: size * 0.36 }}>
      {u.initials}
      {u.official && <span className="g-avatar-badge" style={{ width: size * 0.4, height: size * 0.4 }}><GIcon name="check" size={size * 0.26} /></span>}
    </div>
  );
}

function GMetric({ icon, count, active, onClick, activeColor = "#149a48" }) {
  return (
    <button className={"g-metric" + (active ? " active" : "")} onClick={onClick}
      style={active ? { color: activeColor } : undefined} type="button">
      <span className={active && icon !== "comment" ? "g-metric-fill" : ""} style={active && icon !== "comment" ? { color: activeColor } : undefined}>
        <GIcon name={icon} size={18} />
      </span>
      <span className="g-metric-n">{count}</span>
    </button>
  );
}

function GTag({ label, onClick, active }) {
  return (
    <button type="button" className={"g-tag" + (active ? " active" : "")} onClick={onClick}>#{label}</button>
  );
}

function GCatChip({ category }) {
  const c = guildCat(category);
  return <span className="g-cat" style={{ color: c.color, background: c.color + "1a" }}>{c.label}</span>;
}

function GTopicCard({ topic, state, onOpen, onLike, onBookmark }) {
  const u = GUILD_USERS[topic.author];
  const st = state[topic.id] || {};
  const likes = topic.likes + (st.liked ? 1 : 0);
  const bms = topic.bookmarks + (st.bookmarked ? 1 : 0);
  return (
    <article className="g-card" onClick={() => onOpen(topic.id)}>
      {topic.pinned && <div className="g-pin"><GIcon name="pin" size={13} /> 固定</div>}
      <div className="g-card-top">
        <GCatChip category={topic.category} />
        <span className="g-time">{guildRelTime(topic.createdAt)}</span>
      </div>
      <h3 className="g-card-title">{topic.title}</h3>
      <p className="g-card-body">{topic.body.replace(/#[^\s#　]+/g, "").trim()}</p>
      <div className="g-card-foot" onClick={(e) => e.stopPropagation()}>
        <div className="g-author">
          <GAvatar handle={topic.author} size={28} />
          <span className="g-author-name">{u.name}</span>
        </div>
        <div className="g-metrics">
          <span className="g-metric static"><GIcon name="eye" size={16} /><span className="g-metric-n">{topic.views}</span></span>
          <span className="g-metric static"><GIcon name="comment" size={16} /><span className="g-metric-n">{(GUILD_COMMENTS[topic.id] || []).length}</span></span>
          <GMetric icon="heart" count={likes} active={st.liked} onClick={() => onLike(topic.id)} activeColor="#e0506a" />
          <GMetric icon="bookmark" count={bms} active={st.bookmarked} onClick={() => onBookmark(topic.id)} activeColor="#149a48" />
        </div>
      </div>
    </article>
  );
}

function GHeader({ title, onBack, right }) {
  return (
    <header className="g-header">
      {onBack && (
        <button className="g-iconbtn" onClick={onBack} type="button" aria-label="戻る"><GIcon name="back" size={22} /></button>
      )}
      {title && <h1 className="g-header-title">{title}</h1>}
      <div className="g-header-right">{right}</div>
    </header>
  );
}

function GEmpty({ icon = "bell", text }) {
  return (
    <div className="g-empty">
      <div className="g-empty-ic"><GIcon name={icon} size={26} /></div>
      <p>{text}</p>
    </div>
  );
}

function GSidebar({ route, go, onCreate }) {
  const me = GUILD_USERS[GUILD_ME];
  const items = [
    { key: "home", icon: "home", label: "ホーム" },
    { key: "search", icon: "search", label: "検索" },
    { key: "columns", icon: "column", label: "限定コラム" },
    { key: "notifications", icon: "bell", label: "通知" },
    { key: "bookmarks", icon: "bookmark", label: "ブックマーク" },
    { key: "more", icon: "more", label: "その他" },
  ];
  const active = (k) =>
    route.name === k ||
    (k === "columns" && route.name === "column") ||
    (k === "more" && ["profile", "contact"].includes(route.name));
  return (
    <aside className="g-sidebar">
      <div className="g-side-brand"><img className="g-brand-logo" src="assets/guild-logo.svg" alt="" /><span>ArcAid Guild</span></div>
      <nav className="g-side-nav">
        {items.map((it) => (
          <button key={it.key} type="button" className={"g-side-item" + (active(it.key) ? " active" : "")} onClick={() => go(it.key)}>
            <GIcon name={it.icon} size={21} /><span>{it.label}</span>
          </button>
        ))}
      </nav>
      <button type="button" className="g-side-create" onClick={onCreate}><GIcon name="plus" size={20} /> 新規投稿</button>
      <div className="g-side-spacer"></div>
      <button type="button" className="g-side-me" onClick={() => go("profile", { handle: GUILD_ME })}>
        <GAvatar handle={GUILD_ME} size={42} />
        <div className="g-side-me-main">
          <div className="g-author-name">{me.name}</div>
          <div className="g-handle">@{me.handle}</div>
        </div>
      </button>
    </aside>
  );
}

function GRightRail({ go }) {
  const featured = [...GUILD_TOPICS].sort((a, b) => b.likes - a.likes).slice(0, 4);
  const tags = GUILD_TAGS.slice(0, 8);
  return (
    <aside className="g-rightrail">
      <div className="g-rail-card g-rail-cta">
        <h4>テスラの保険、見直しませんか？</h4>
        <p>ギルド会員のあなたへ。プレミアム補償込みの概算は約1分で。</p>
        <a className="g-rail-btn" href="quote.html">無料で見積もる →</a>
      </div>
      <div className="g-rail-card">
        <h4>注目のトピック</h4>
        {featured.map((t, i) => (
          <button key={t.id} type="button" className="g-rail-topic" onClick={() => go("topic", { id: t.id })}>
            <span className="g-rail-rank">{i + 1}</span>
            <span>
              <h5>{t.title}</h5>
              <span className="g-mini">{(GUILD_COMMENTS[t.id] || []).length} コメント · {t.likes} いいね</span>
            </span>
          </button>
        ))}
      </div>
      <div className="g-rail-card">
        <h4>人気のタグ</h4>
        <div className="g-rail-tags">
          {tags.map((t) => <GTag key={t} label={t} onClick={() => go("search", { tag: t })} />)}
        </div>
      </div>
    </aside>
  );
}

function GBottomNav({ route, go, onCreate }) {
  const items = [
    { key: "home", icon: "home", label: "ホーム" },
    { key: "search", icon: "search", label: "検索" },
    { key: "columns", icon: "column", label: "限定コラム" },
    { key: "notifications", icon: "bell", label: "通知" },
    { key: "more", icon: "more", label: "その他" },
  ];
  const active = (k) => route.name === k || (k === "columns" && route.name === "column") || (k === "more" && ["profile", "bookmarks", "contact"].includes(route.name));
  return (
    <nav className="g-bottomnav">
      {items.slice(0, 2).map((it) => (
        <button key={it.key} type="button" className={"g-navitem" + (active(it.key) ? " active" : "")} onClick={() => go(it.key)}>
          <GIcon name={it.icon} size={22} /><span>{it.label}</span>
        </button>
      ))}
      <button type="button" className="g-fab" onClick={onCreate} aria-label="新規投稿"><GIcon name="plus" size={26} /></button>
      {items.slice(3).map((it) => (
        <button key={it.key} type="button" className={"g-navitem" + (active(it.key) ? " active" : "")} onClick={() => go(it.key)}>
          <GIcon name={it.icon} size={22} /><span>{it.label}</span>
        </button>
      ))}
    </nav>
  );
}

Object.assign(window, { GIcon, GAvatar, GMetric, GTag, GCatChip, GTopicCard, GHeader, GEmpty, GBottomNav, GSidebar, GRightRail });
