{# ══════════════════════════════════════════════
   MACROS — must come before first use in Jinja2
══════════════════════════════════════════════ #}

{# List view: indented tree with ├── / └── connector lines.
   open_stack: list of booleans — True = ancestor has more siblings (draw vert), False = last (draw blank).
   is_last: whether this node is the last sibling among its parent's children. #}
{% macro render_list_item(qid, quest_by_id, children, visible, collector_prereqs, open_stack, is_last, collector_id) %}
{% set q = quest_by_id[qid] %}
{% set visible_kids = [] %}
{% for cid in children.get(qid, []) %}
  {% if cid in visible %}{% set _ = visible_kids.append(cid) %}{% endif %}
{% endfor %}
<div class="list-item">
  <div class="list-indent">
    {% for open in open_stack %}
      <div class="list-indent-seg {{ 'vert' if open else 'blank' }}"></div>
    {% endfor %}
    {% if open_stack %}
      <div class="list-indent-seg {{ 'elbow' if is_last else 'tee' }}"></div>
    {% endif %}
  </div>
  <div class="list-row{% if q.done %} done{% endif %}"
       data-id="{{ qid }}" data-done="{{ '1' if q.done else '0' }}"
       data-counted="{{ '1' if qid in collector_prereqs else '0' }}">
    {% if qid in collector_prereqs %}<span class="kappa-star">★</span>{% endif %}
    <span class="list-name">{{ q.name }}</span>
    {% if q.wiki_link %}<a class="list-wiki" href="{{ q.wiki_link }}" target="_blank">wiki</a>{% endif %}
    {% if qid != collector_id %}<button class="toggle-btn" onclick="toggle(this)">{{ '✓' if q.done else '○' }}</button>{% endif %}
  </div>
</div>
{% set child_stack = open_stack + [not is_last] %}
{% for cid in visible_kids %}
  {% set child = quest_by_id[cid] %}
  {% set child_last = loop.last %}
  {% if child.trader != q.trader %}
    <div class="list-item">
      <div class="list-indent">
        {% for open in child_stack %}
          <div class="list-indent-seg {{ 'vert' if open else 'blank' }}"></div>
        {% endfor %}
        <div class="list-indent-seg {{ 'elbow' if child_last else 'tee' }}"></div>
      </div>
      <div class="list-row{% if child.done %} done{% endif %}"
           data-id="{{ cid }}" data-done="{{ '1' if child.done else '0' }}"
           data-counted="{{ '1' if cid in collector_prereqs else '0' }}">
        {% if cid in collector_prereqs %}<span class="kappa-star">★</span>{% endif %}
        <span class="list-name">{{ child.name }}</span>
        {% if child.wiki_link %}<a class="list-wiki" href="{{ child.wiki_link }}" target="_blank">wiki</a>{% endif %}
        <span class="cross-badge">{{ child.trader }}</span>
        {% if cid != collector_id %}<button class="toggle-btn" onclick="toggle(this)">{{ '✓' if child.done else '○' }}</button>{% endif %}
      </div>
    </div>
  {% else %}
    {{ render_list_item(cid, quest_by_id, children, visible, collector_prereqs, child_stack, child_last, collector_id) }}
  {% endif %}
{% endfor %}
{% endmacro %}

<!doctype html>
<html>
<head>
  <title>OnlyScavs – Collector Checklist</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    :root {
      --bg: #121212;
      --panel: #1a1a1a;
      --text: #eee;
      --muted: #888;
      --border: #2a2a2a;
      --accent: #9ccfff;
      --done-text: #6ec96e;
      --done-bg: #1a2a1a;
      --kappa: #f0c040;
      --line: #333;
    }
    * { box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      background: var(--bg);
      color: var(--text);
      margin: 0;
      padding-top: 52px;
      background-image: url('/assets/onlyscavs.png');
      background-attachment: fixed;
      background-size: cover;
      background-position: center 65%;
    }
    body::before {
      content: '';
      position: fixed;
      inset: 0;
      background: rgba(14,14,14,0.88);
      pointer-events: none;
      z-index: 0;
    }
    .page { max-width: 960px; margin: 0 auto; padding: 24px 16px; position: relative; z-index: 1; }
    .site-nav {
      position: fixed; top: 0; left: 0; right: 0; z-index: 100;
      display: flex; align-items: center; justify-content: space-between;
      padding: 0 24px; height: 52px;
      background: rgba(14,14,14,0.92);
      backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
      border-bottom: 1px solid rgba(255,255,255,0.06);
    }
    .nav-brand { font-size: 0.85rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); text-decoration: none; flex-shrink: 0; }
    .nav-links { display: flex; gap: 2px; flex-wrap: wrap; }
    .nav-links a { color: #666; text-decoration: none; font-size: 0.8rem; padding: 5px 10px; border-radius: 5px; transition: color 0.15s, background 0.15s; }
    .nav-links a:hover { color: var(--text); background: rgba(255,255,255,0.06); }
    .nav-links a.active { color: var(--accent); background: rgba(156,207,255,0.08); }
    h1 { margin: 0 0 4px; }
    .toolbar {
      display: flex;
      align-items: center;
      gap: 10px;
      flex-wrap: wrap;
      margin-bottom: 12px;
    }
    .filter-btn {
      background: var(--panel);
      border: 1px solid #444;
      color: var(--text);
      border-radius: 6px;
      padding: 5px 14px;
      cursor: pointer;
      font-size: 0.85rem;
      text-decoration: none;
    }
    .filter-btn.active { border-color: var(--kappa); color: var(--kappa); }
    .sep { color: var(--border); }
    .subtitle {
      color: var(--muted);
      margin: 0 0 16px;
      font-size: 0.95rem;
    }
    .progress-bar-wrap {
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: 999px;
      height: 10px;
      margin-bottom: 20px;
      overflow: hidden;
    }
    .progress-bar-fill {
      background: var(--done-text);
      height: 100%;
      border-radius: 999px;
      transition: width 0.3s;
    }
    .legend {
      display: flex;
      gap: 16px;
      font-size: 0.8rem;
      color: var(--muted);
      flex-wrap: wrap;
      margin-bottom: 16px;
    }
    .legend span { display: flex; align-items: center; gap: 5px; }

    /* Trader section */
    .trader-section { margin-bottom: 8px; }
    .trader-header {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 10px 8px;
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: 6px;
      cursor: pointer;
      user-select: none;
    }
    .trader-header:hover { border-color: #444; }
    .trader-name {
      font-weight: bold;
      font-size: 0.95rem;
      flex: 1;
    }
    .trader-counts { font-size: 0.8rem; color: var(--muted); }
    .chevron { color: var(--muted); font-size: 0.8rem; transition: transform 0.15s; }
    .trader-section.collapsed .chevron { transform: rotate(-90deg); }
    .trader-body { padding: 6px 0 6px 8px; }
    .trader-section.collapsed .trader-body { display: none; }

    /* Flow tree */
    .tree-root {
      margin: 6px 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      position: relative;
    }
    .tree-children {
      display: flex;
      gap: 14px;
      align-items: flex-start;
      justify-content: center;
      position: relative;
      padding-top: 18px;
      flex-wrap: wrap;
    }
    .tree-children:before {
      content: "";
      position: absolute;
      top: 8px;
      left: 8px;
      right: 8px;
      height: 1px;
      background: var(--border);
      opacity: 0.9;
    }
    .tree-children > .tree-root {
      padding-top: 8px;
    }
    .tree-children > .tree-root:before {
      content: "";
      position: absolute;
      top: 0;
      left: 50%;
      width: 1px;
      height: 8px;
      background: var(--border);
    }
    .quest-node {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 5px 6px;
      border-radius: 4px;
      margin: 2px 0;
      position: relative;
      background: #141820;
      border: 1px solid #1b2230;
    }
    .quest-node.has-children:after {
      content: "";
      position: absolute;
      left: 50%;
      bottom: -8px;
      width: 1px;
      height: 8px;
      background: var(--border);
    }
    .quest-node:hover { background: #1e1e1e; }
    .quest-node.done .quest-label { text-decoration: line-through; color: var(--done-text); }
    .quest-node.done { background: var(--done-bg); }
    .quest-label { flex: 1; font-size: 0.9rem; }
    .quest-label a { color: var(--accent); font-size: 0.75rem; margin-left: 6px; }
    .kappa-star { color: var(--kappa); font-size: 0.75rem; flex-shrink: 0; }
    .cross-trader {
      font-size: 0.75rem;
      color: var(--muted);
      font-style: italic;
      flex-shrink: 0;
    }
    .toggle-btn {
      background: transparent;
      border: 1px solid #444;
      color: var(--muted);
      border-radius: 4px;
      padding: 2px 7px;
      cursor: pointer;
      font-size: 0.75rem;
      flex-shrink: 0;
    }
    .quest-node.done .toggle-btn {
      border-color: #3a6a3a;
      color: var(--done-text);
    }

    /* ── LIST VIEW ──
       Classic file-manager tree: ├── and └── connectors. */
    .list-view .trader-body { padding: 4px 0; }
    .list-tree { padding: 0; margin: 0; }
    .list-item { display: flex; align-items: flex-start; }
    .list-indent { display: flex; flex-shrink: 0; }
    .list-indent-seg { width: 20px; flex-shrink: 0; position: relative; min-height: 30px; }
    .list-indent-seg.vert::before {
      content: ""; position: absolute; top: 0; bottom: 0; left: 9px; width: 1px; background: var(--line);
    }
    .list-indent-seg.tee::before {
      content: ""; position: absolute; top: 0; bottom: 0; left: 9px; width: 1px; background: var(--line);
    }
    .list-indent-seg.tee::after {
      content: ""; position: absolute; top: 50%; left: 9px; width: 11px; height: 1px; background: var(--line);
    }
    .list-indent-seg.elbow::before {
      content: ""; position: absolute; top: 0; bottom: 50%; left: 9px; width: 1px; background: var(--line);
    }
    .list-indent-seg.elbow::after {
      content: ""; position: absolute; top: 50%; left: 9px; width: 11px; height: 1px; background: var(--line);
    }
    .list-indent-seg.blank {}
    .list-row {
      flex: 1; display: flex; align-items: center; gap: 6px;
      padding: 4px 6px 4px 2px; border-radius: 4px; margin: 1px 0;
      background: transparent; min-height: 30px;
    }
    .list-row:hover { background: #1a1a1a; }
    .list-row.done .list-name { text-decoration: line-through; color: var(--done-text); }
    .list-name { font-size: 0.85rem; flex: 1; }
    .list-wiki { color: var(--accent); font-size: 0.72rem; text-decoration: none; flex-shrink: 0; }
    .list-wiki:hover { text-decoration: underline; }
    .list-row .kappa-star { font-size: 0.72rem; }
    .list-row .cross-badge { font-size: 0.7rem; }
    .list-row .toggle-btn { font-size: 0.72rem; }
    .list-row.done .toggle-btn { border-color: #3a6a3a; color: var(--done-text); }

    .flow-view.hidden, .list-view.hidden { display: none; }
  </style>
</head>
<body>
<div class="page">
  <nav class="site-nav">
    <a class="nav-brand" href="/">OnlyScavs</a>
    <div class="nav-links">
      <a href="/keys">Keys</a>
      <a href="/collector" class="active">Collector</a>
      <a href="/quests">Quests</a>
      <a href="/loadout">Loadout</a>
      <a href="/meds">Injectors</a>
      <a href="/barters">Barters</a>
    </div>
  </nav>
  <h1>Collector Checklist</h1>
  <p class="subtitle">
    {{ done }} / {{ total }} quests completed
  </p>

  <div class="progress-bar-wrap">
    <div class="progress-bar-fill" style="width: {{ (done / total * 100) | round(1) if total else 0 }}%"></div>
  </div>

  <div class="toolbar">
    <a class="filter-btn {% if view != 'list' %}active{% endif %}" href="/collector?view=flow">Flow</a>
    <a class="filter-btn {% if view == 'list' %}active{% endif %}" href="/collector?view=list">List</a>
    <span class="sep">|</span>
    <button class="filter-btn" type="button" onclick="setAllTradersCollapsed(true)">Collapse all</button>
    <button class="filter-btn" type="button" onclick="setAllTradersCollapsed(false)">Expand all</button>
  </div>

  <div class="legend">
    <span><span style="color:var(--kappa)">★</span> Required for Collector</span>
    <span><span style="color:var(--done-text)">✓</span> Marked done</span>
    <span><span style="color:var(--muted);font-style:italic">← Trader</span> Cross-trader dependency</span>
  </div>

{% macro render_node(qid, quest_by_id, children, visible, collector_prereqs, collector_id, is_root=False) %}
{% set q = quest_by_id[qid] %}
{% set visible_kids = [] %}
{% for cid in children.get(qid, []) %}
  {% if cid in visible %}{% set _ = visible_kids.append(cid) %}{% endif %}
{% endfor %}
<div class="tree-root">
  <div class="quest-node {% if q.done %}done{% endif %} {% if is_root %}root-node{% endif %}{% if visible_kids %} has-children{% endif %}"
       id="qnode-{{ qid }}"
       data-id="{{ qid }}"
       data-done="{{ '1' if q.done else '0' }}"
       data-counted="{{ '1' if qid in collector_prereqs else '0' }}">
    {% if qid in collector_prereqs %}<span class="kappa-star" title="Required for Collector">★</span>{% endif %}
    <span class="quest-label">
      {{ q.name }}
      {% if q.wiki_link %}<a href="{{ q.wiki_link }}" target="_blank">wiki</a>{% endif %}
    </span>
    {% if qid != collector_id %}
      <button class="toggle-btn" onclick="toggle(this)">
        {{ '✓' if q.done else '○' }}
      </button>
    {% endif %}
  </div>
  {% if visible_kids %}
  <div class="tree-children">
    {% for cid in visible_kids %}
      {% set child = quest_by_id[cid] %}
      {% if child.trader != q.trader %}
        <div class="quest-node {% if child.done %}done{% endif %}"
             data-id="{{ cid }}"
             data-done="{{ '1' if child.done else '0' }}"
             data-counted="{{ '1' if cid in collector_prereqs else '0' }}">
          {% if cid in collector_prereqs %}<span class="kappa-star">★</span>{% endif %}
          <span class="quest-label">
            {{ child.name }}
            {% if child.wiki_link %}<a href="{{ child.wiki_link }}" target="_blank">wiki</a>{% endif %}
          </span>
          <span class="cross-trader">← {{ child.trader }}</span>
          {% if cid != collector_id %}
            <button class="toggle-btn" onclick="toggle(this)">{{ '✓' if child.done else '○' }}</button>
          {% endif %}
        </div>
      {% else %}
        {{ render_node(cid, quest_by_id, children, visible, collector_prereqs, collector_id, false) }}
      {% endif %}
    {% endfor %}
  </div>
  {% endif %}
</div>
{% endmacro %}

  {# ── FLOW VIEW ── #}
  <div class="flow-view {% if view == 'list' %}hidden{% endif %}">
  {% for trader in traders %}
    {% set roots = trader_roots[trader] %}
    {% set total_trader = namespace(n=0) %}
    {% set done_trader = namespace(n=0) %}
    {% for qid in visible %}
      {% if quest_by_id[qid].trader == trader and qid in collector_prereqs %}
        {% set total_trader.n = total_trader.n + 1 %}
        {% if quest_by_id[qid].done %}{% set done_trader.n = done_trader.n + 1 %}{% endif %}
      {% endif %}
    {% endfor %}

    <div class="trader-section" id="flow-{{ trader | replace(' ', '-') }}">
      <div class="trader-header" onclick="toggleTrader(this)">
        <span class="trader-name">{{ trader }}</span>
        <span class="trader-counts">{{ done_trader.n }} / {{ total_trader.n }}</span>
        <span class="chevron">▾</span>
      </div>
      <div class="trader-body">
        {% for root_id in roots %}
          {{ render_node(root_id, quest_by_id, children, visible, collector_prereqs, collector_id, true) }}
        {% endfor %}
      </div>
    </div>
  {% endfor %}
  </div>

  {# ── LIST VIEW ── #}
  <div class="list-view {% if view != 'list' %}hidden{% endif %}">
  {% for trader in traders %}
    {% set roots = trader_roots[trader] %}
    {% set total_trader = namespace(n=0) %}
    {% set done_trader = namespace(n=0) %}
    {% for qid in visible %}
      {% if quest_by_id[qid].trader == trader and qid in collector_prereqs %}
        {% set total_trader.n = total_trader.n + 1 %}
        {% if quest_by_id[qid].done %}{% set done_trader.n = done_trader.n + 1 %}{% endif %}
      {% endif %}
    {% endfor %}

    <div class="trader-section" id="list-{{ trader | replace(' ', '-') }}">
      <div class="trader-header" onclick="toggleTrader(this)">
        <span class="trader-name">{{ trader }}</span>
        <span class="trader-counts">{{ done_trader.n }} / {{ total_trader.n }}</span>
        <span class="chevron">▾</span>
      </div>
      <div class="trader-body">
        <div class="list-tree">
          {% for root_id in roots %}
            {{ render_list_item(root_id, quest_by_id, children, visible, collector_prereqs, [], loop.last, collector_id) }}
          {% endfor %}
        </div>
      </div>
    </div>
  {% endfor %}
  </div>

</div>

<script>
  let doneCount = {{ done }};
  const total = {{ total }};

  function updateProgress() {
    document.querySelector('.subtitle').textContent = doneCount + ' / ' + total + ' quests completed';
    const pct = total ? (doneCount / total * 100).toFixed(1) : 0;
    document.querySelector('.progress-bar-fill').style.width = pct + '%';
  }

  function toggleTrader(header) {
    const section = header.closest('.trader-section');
    section.classList.toggle('collapsed');
    persistCollapsed();
  }

  function setAllTradersCollapsed(collapsed) {
    document.querySelectorAll('.trader-section').forEach(section => {
      section.classList.toggle('collapsed', collapsed);
    });
    persistCollapsed();
  }

  const COLLAPSE_KEY = 'collector.collapsedTraders2';

  function persistCollapsed() {
    const collapsed = Array.from(document.querySelectorAll('.trader-section.collapsed'))
      .map(s => s.id);
    localStorage.setItem(COLLAPSE_KEY, JSON.stringify(collapsed));
  }

  function restoreCollapsed() {
    try {
      const raw = localStorage.getItem(COLLAPSE_KEY);
      if (!raw) return;
      const ids = JSON.parse(raw);
      if (!Array.isArray(ids)) return;
      ids.forEach(id => {
        const section = document.getElementById(id);
        if (section) section.classList.add('collapsed');
      });
    } catch (e) {
      // ignore storage/parse errors
    }
  }

  restoreCollapsed();

  function toggle(btn) {
    const node = btn.closest('[data-id]');
    const id = node.dataset.id;
    const wasDone = node.dataset.done === '1';
    const nowDone = wasDone ? 0 : 1;

    fetch('/collector/toggle', {
      method: 'POST',
      body: new URLSearchParams({ quest_id: id, done: nowDone })
    })
    .then(r => r.json())
    .then(() => {
      document.querySelectorAll(`[data-id="${id}"]`).forEach(n => {
        n.dataset.done = nowDone;
        const b = n.querySelector('.toggle-btn');
        if (b) {
          if (nowDone) { n.classList.add('done'); b.textContent = '✓'; }
          else          { n.classList.remove('done'); b.textContent = '○'; }
        }
      });

      if (node.dataset.counted === '1') {
        doneCount += nowDone ? 1 : -1;
        updateProgress();
      }
    });
  }
</script>
</body>
</html>
