// Akashic Record — Hub
const { useState, useEffect, useMemo } = React;

// ============ Icons (inline SVG) ============
const Icon = {
  Search: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><circle cx="7" cy="7" r="5" stroke="currentColor" strokeWidth="1.5"/><path d="M11 11l3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  Grid: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><rect x="2" y="2" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.4"/><rect x="9" y="2" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.4"/><rect x="2" y="9" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.4"/><rect x="9" y="9" width="5" height="5" rx="1" stroke="currentColor" strokeWidth="1.4"/></svg>,
  List: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  Clock: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.4"/><path d="M8 5v3l2 1.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  Note: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M3 2h7l3 3v9H3z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/><path d="M10 2v3h3" stroke="currentColor" strokeWidth="1.4"/></svg>,
  Tool: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M11 2l3 3-7 7-3-3z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/><path d="M2 14l2-2" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>,
  Book: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M3 3h5a2 2 0 012 2v9H5a2 2 0 01-2-2V3zM13 3H8a2 2 0 00-2 2v9h5a2 2 0 002-2V3z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>,
  External: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M6 3H3v10h10v-3M9 3h4v4M13 3l-6 6" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  Star: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M8 2l1.8 4 4.2.5-3 3 .8 4.2L8 11.5 4.2 13.7 5 9.5l-3-3 4.2-.5z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>,
  Arrow: (p) => <svg viewBox="0 0 16 16" fill="none" {...p}><path d="M6 3l5 5-5 5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>,
};

const STATUS_LABEL = { playing: "진행중", completed: "완료", waiting: "대기" };

// ============ Header ============
function Header({ search, setSearch, totalGames, activeGames }) {
  return (
    <header className="hdr">
      <div className="hdr-brand">
        <div className="hdr-logo" />
        <div className="hdr-title">
          <div className="hdr-title-main">Akashic Record</div>
          <div className="hdr-title-sub">Personal Game Hub</div>
        </div>
      </div>

      <div className="hdr-search">
        <Icon.Search className="hdr-search-icon" width={16} height={16} />
        <input
          className="hdr-search-input"
          placeholder="게임, 태그, 공략 검색…"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
        />
        <span className="hdr-search-kbd">⌘K</span>
      </div>

      <div className="hdr-stats">
        <div className="hdr-stat">
          <span className="hdr-stat-num">{totalGames}</span>
          <span>games</span>
        </div>
        <div className="hdr-stat">
          <span className="hdr-stat-dot" />
          <span className="hdr-stat-num">{activeGames}</span>
          <span>active</span>
        </div>
      </div>
    </header>
  );
}

// ============ Filter Bar ============
function FilterBar({ filters, setFilters, view, setView, sort, setSort, counts }) {
  const setStatus = (s) => setFilters({ ...filters, status: s });
  const togglePlatform = (p) => {
    const cur = filters.platforms;
    setFilters({ ...filters, platforms: cur.includes(p) ? cur.filter(x => x !== p) : [...cur, p] });
  };

  return (
    <div className="filter-bar">
      <div className="filter-group">
        <span className="filter-label">상태</span>
        {Object.entries(window.CATEGORIES).map(([key, c]) => (
          <button
            key={key}
            className={`chip ${filters.status === key ? "chip-active" : ""}`}
            onClick={() => setStatus(key)}
          >
            {c.label}
            <span className="chip-count">{counts[key] ?? 0}</span>
          </button>
        ))}
      </div>

      <div className="filter-group">
        <span className="filter-label">플랫폼</span>
        {window.PLATFORMS.map(p => (
          <button
            key={p}
            className={`chip ${filters.platforms.includes(p) ? "chip-active" : ""}`}
            onClick={() => togglePlatform(p)}
          >{p}</button>
        ))}
      </div>

      <div className="filter-right">
        <select className="sort-select" value={sort} onChange={(e) => setSort(e.target.value)}>
          <option value="recent">최근 활동순</option>
          <option value="name">이름순</option>
          <option value="playtime">플레이타임순</option>
          <option value="progress">진행도순</option>
        </select>
        <div className="view-toggle">
          <button className={view === "grid" ? "active" : ""} onClick={() => setView("grid")}>
            <Icon.Grid width={13} height={13} />
            그리드
          </button>
          <button className={view === "list" ? "active" : ""} onClick={() => setView("list")}>
            <Icon.List width={13} height={13} />
            리스트
          </button>
        </div>
      </div>
    </div>
  );
}

// ============ Card (Grid) ============
function Card({ game, onClick }) {
  const href = `games/${game.id}/`;
  return (
    <article className="card" onClick={() => onClick(game)}>
      <div className="card-cover">
        <div className="card-cover-img" style={{ background: game.coverGradient }}>
          <span className="card-cover-glyph">{game.coverGlyph}</span>
        </div>
        <div className="card-cover-overlay" />
        <div className="card-cover-meta">
          <span className="card-platform">{game.platform}</span>
          <span className="card-status" data-status={game.status}>
            <span className="card-status-dot" />
            {STATUS_LABEL[game.status]}
          </span>
        </div>
      </div>

      <div className="card-body">
        <div className="card-genre">{game.genre}</div>
        <h3 className="card-title">{game.title}</h3>
        {game.subtitle && <div className="card-subtitle">{game.subtitle}</div>}

        {game.progress != null && (
          <div>
            <div className="card-progress-row">
              <span>진행도</span>
              <span>{Math.round(game.progress * 100)}%</span>
            </div>
            <div className="card-progress-bar">
              <div className="card-progress-fill" style={{ width: `${game.progress * 100}%` }} />
            </div>
          </div>
        )}

        <div className="card-footer">
          <div className="card-last">
            <Icon.Clock width={11} height={11} />
            <span className="card-last-time">{window.fmtRelative(game.lastPlayed)}</span>
          </div>
          <div className="card-resources">
            <span><Icon.Note width={10} height={10} /><b>{game.notes}</b></span>
            <span><Icon.Tool width={10} height={10} /><b>{game.tools}</b></span>
            <span><Icon.Book width={10} height={10} /><b>{game.guides}</b></span>
          </div>
        </div>
      </div>

      <div className="card-edge" />
    </article>
  );
}

// ============ Row (List) ============
function Row({ game, onClick }) {
  const STATUS_DOT = { playing: "var(--neon)", completed: "var(--cyan-400)", waiting: "var(--ink-4)" };
  return (
    <div className="row" onClick={() => onClick(game)}>
      <div className="row-cover" style={{ background: game.coverGradient }}>
        <span className="row-cover-glyph">{game.coverGlyph}</span>
      </div>
      <div className="row-title-block">
        <div className="row-title">{game.title}</div>
        <div className="row-genre">{game.genre} · {game.platform}</div>
      </div>
      <div className="row-status">
        <span className="row-status-dot" style={{
          background: STATUS_DOT[game.status],
          boxShadow: game.status === "playing" ? "0 0 8px var(--neon-glow)" : "none"
        }} />
        {STATUS_LABEL[game.status]}
      </div>
      <div className="row-platform">{game.tags?.[0] ?? ""}</div>
      <div className="row-progress">
        {game.progress != null ? (
          <>
            <div className="row-progress-bar">
              <div className="row-progress-fill" style={{ width: `${game.progress * 100}%` }} />
            </div>
            <div className="row-progress-text">{Math.round(game.progress * 100)}% · {game.playtimeHours}h</div>
          </>
        ) : (
          <div className="row-progress-text">— · {game.playtimeHours}h</div>
        )}
      </div>
      <div className="row-last">
        <div>{window.fmtRelative(game.lastPlayed)}</div>
        <div className="row-last-rel">notes {game.notes} · tools {game.tools}</div>
      </div>
    </div>
  );
}

// ============ Preview Panel ============
function Preview({ game, onClose }) {
  const open = !!game;
  const [lastGame, setLastGame] = useState(null);
  useEffect(() => { if (game) setLastGame(game); }, [game]);
  const g = game || lastGame;

  if (!g) return null;

  const resources = [
    { type: "guide",    title: "메인 스토리 공략",       meta: `${g.guides}개 항목`,                icon: <Icon.Book width={14} height={14} /> },
    { type: "tool",     title: "빌드 / 시너지 계산기",   meta: `${g.tools}개 도구`,                 icon: <Icon.Tool width={14} height={14} /> },
    { type: "note",     title: "개인 메모",              meta: `${g.notes}개 메모`,                 icon: <Icon.Note width={14} height={14} /> },
    { type: "external", title: "외부 위키",              meta: "외부 링크",                          icon: <Icon.External width={13} height={13} /> },
  ];

  const openGamePage = () => {
    if (g.id) window.location.href = `games/${g.id}/`;
  };

  return (
    <>
      <div className={`preview-overlay ${open ? "open" : ""}`} onClick={onClose} />
      <aside className={`preview-panel ${open ? "open" : ""}`}>
        <div className="preview-hero">
          <div className="preview-hero-bg" style={{ background: g.coverGradient }}>
            <span className="preview-hero-glyph">{g.coverGlyph}</span>
          </div>
          <button className="preview-close" onClick={onClose} aria-label="닫기">×</button>
          <div className="preview-hero-text">
            <div className="preview-hero-genre">{g.genre} · {g.platform}</div>
            <h2 className="preview-hero-title">{g.title}</h2>
            {g.subtitle && <div className="preview-hero-sub">{g.subtitle}</div>}
          </div>
        </div>

        <div className="preview-body">
          <p className="preview-summary">{g.summary}</p>

          <div>
            <div className="preview-section-label">상태</div>
            <div className="preview-stats">
              <div className="preview-stat">
                <div className="preview-stat-label">플레이타임</div>
                <div className="preview-stat-value">{g.playtimeHours}<span className="preview-stat-suffix">h</span></div>
              </div>
              <div className="preview-stat">
                <div className="preview-stat-label">진행도</div>
                <div className="preview-stat-value">
                  {g.progress != null ? Math.round(g.progress * 100) : "—"}
                  {g.progress != null && <span className="preview-stat-suffix">%</span>}
                </div>
              </div>
              <div className="preview-stat">
                <div className="preview-stat-label">마지막 활동</div>
                <div className="preview-stat-value" style={{ fontSize: 15, marginTop: 8 }}>
                  {window.fmtRelative(g.lastPlayed)}
                </div>
              </div>
            </div>
          </div>

          <div>
            <div className="preview-section-label">리소스</div>
            <div className="preview-resources">
              {resources.map(r => (
                <div className="preview-resource" key={r.type}>
                  <div className="preview-resource-left">
                    <div className="preview-resource-icon">{r.icon}</div>
                    <div className="preview-resource-text">
                      <div className="preview-resource-title">{r.title}</div>
                      <div className="preview-resource-meta">{r.meta}</div>
                    </div>
                  </div>
                  <Icon.Arrow width={12} height={12} className="preview-resource-arrow" />
                </div>
              ))}
            </div>
          </div>

          {g.tags?.length > 0 && (
            <div>
              <div className="preview-section-label">태그</div>
              <div className="preview-tags">
                {g.tags.map(t => <span key={t} className="preview-tag">#{t}</span>)}
              </div>
            </div>
          )}

          <div className="preview-cta">
            <button className="preview-btn" onClick={openGamePage}>
              <Icon.External width={14} height={14} />
              게임 페이지 열기
            </button>
            <button className="preview-btn preview-btn-secondary" aria-label="즐겨찾기">
              <Icon.Star width={15} height={15} />
            </button>
          </div>
        </div>
      </aside>
    </>
  );
}

// ============ App ============
function App() {
  const [games, setGames] = useState([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState(null);
  const [search, setSearch] = useState("");
  const [view, setView] = useState("grid");
  const [sort, setSort] = useState("recent");
  const [filters, setFilters] = useState({ status: "all", platforms: [], genres: [] });
  const [selected, setSelected] = useState(null);

  // 초기 로드
  useEffect(() => {
    window.loadGames()
      .then((g) => { setGames(g); setLoading(false); })
      .catch((err) => { setLoadError(err.message); setLoading(false); });
  }, []);

  // Esc closes panel
  useEffect(() => {
    const h = (e) => { if (e.key === "Escape") setSelected(null); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, []);

  const filtered = useMemo(() => {
    let list = games;
    if (filters.status !== "all") list = list.filter(g => g.status === filters.status);
    if (filters.platforms.length) list = list.filter(g => filters.platforms.includes(g.platform));
    if (filters.genres.length) list = list.filter(g => filters.genres.includes(g.genre));
    if (search.trim()) {
      const q = search.toLowerCase();
      list = list.filter(g =>
        g.title.toLowerCase().includes(q) ||
        g.genre.toLowerCase().includes(q) ||
        (g.tags ?? []).some(t => t.toLowerCase().includes(q))
      );
    }
    const sorted = [...list];
    if (sort === "recent")   sorted.sort((a, b) => new Date(b.lastPlayed) - new Date(a.lastPlayed));
    if (sort === "name")     sorted.sort((a, b) => a.title.localeCompare(b.title));
    if (sort === "playtime") sorted.sort((a, b) => b.playtimeHours - a.playtimeHours);
    if (sort === "progress") sorted.sort((a, b) => (b.progress ?? 0) - (a.progress ?? 0));
    return sorted;
  }, [games, filters, search, sort]);

  const counts = useMemo(() => window.computeCounts(games), [games]);
  const activeGames = counts.playing ?? 0;

  if (loading) {
    return (
      <div style={{ padding: 80, textAlign: "center", color: "var(--ink-3)" }}>
        Loading…
      </div>
    );
  }
  if (loadError) {
    return (
      <div style={{ padding: 80, textAlign: "center", color: "var(--ink-2)" }}>
        <p>games.json을 못 불러왔어 — {loadError}</p>
      </div>
    );
  }

  return (
    <div>
      <Header
        search={search}
        setSearch={setSearch}
        totalGames={games.length}
        activeGames={activeGames}
      />
      <FilterBar
        filters={filters}
        setFilters={setFilters}
        view={view}
        setView={setView}
        sort={sort}
        setSort={setSort}
        counts={counts}
      />

      {filtered.length === 0 ? (
        <div style={{ padding: "60px 40px", textAlign: "center", color: "var(--ink-3)" }}>
          조건에 맞는 게임이 없어. 필터를 풀거나 새 게임을 추가해줘.
        </div>
      ) : view === "grid" ? (
        <div className="cards-grid">
          {filtered.map(g => <Card key={g.id} game={g} onClick={setSelected} />)}
        </div>
      ) : (
        <div className="cards-list">
          {filtered.map(g => <Row key={g.id} game={g} onClick={setSelected} />)}
        </div>
      )}

      <Preview game={selected} onClose={() => setSelected(null)} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("app")).render(<App />);
