{% extends "base.html" %}
{% block title %}{{ BRAND_NAME }} · Settings{% endblock %}

{% block main %}
<section class="panel" style="grid-column: 1 / -1; max-width: 760px; margin: 0 auto;">
  <div class="panel-header">
    <span class="title">Settings</span>
    <span class="meta">your account &middot; client-only data unchanged</span>
  </div>
  <div class="panel-body" style="padding: 18px clamp(16px, 4vw, 32px) 24px;">

    {% if not user %}
      <div class="empty">no per-user settings (admin bearer-token session)</div>
    {% else %}

    <div class="settings-row">
      <div class="settings-row__label">Email</div>
      <div class="settings-row__value">{{ user.email }}</div>
    </div>

    <div class="settings-row">
      <div class="settings-row__label">Tier</div>
      <div class="settings-row__value" style="display:flex; align-items:flex-start; gap:10px; flex:1;">
        <div style="flex:1; min-width:0;">
          <span class="badge {% if paid and paid.active %}badge--ok{% else %}badge--ver{% endif %}">
            {{ user.tier }}{% if paid and paid.active and paid.source == "credit" %} · credit{% endif %}
          </span>
          {% if paid and paid.active %}
            {% if paid.source == "credit" %}
              <span class="settings-row__hint">
                Paid features active via credit · {{ paid.days_remaining }} day(s) remaining
                (expires {{ paid.expires_at.strftime("%Y-%m-%d") }}).
              </span>
            {% else %}
              {% if trial_days_remaining %}
                <span class="settings-row__hint">
                  <strong>Free trial</strong> &mdash; {{ trial_days_remaining }}
                  day{{ '' if trial_days_remaining == 1 else 's' }} remaining.
                  Cancel before the trial ends and you won&rsquo;t be charged.
                </span>
              {% else %}
                <span class="settings-row__hint">Paid subscription active.</span>
              {% endif %}
            {% endif %}
          {% else %}
            <span class="settings-row__hint">
              Free tier &mdash; <a href="/pricing">upgrade for £7/month or £70/year</a>.
            </span>
          {% endif %}
        </div>
        {% if paid and paid.active and paid.source != "credit" and user.stripe_customer_id %}
          <button type="button" id="stripe-portal-btn" class="settings-icon-btn"
                  title="Manage subscription — payment method, invoices, plan, cancel"
                  aria-label="Manage subscription">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
              <path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/>
            </svg>
          </button>
        {% endif %}
      </div>
    </div>

    {% if paid and paid.active and paid.source != "credit" and user.stripe_customer_id %}
    <script>
    (function () {
      var btn = document.getElementById('stripe-portal-btn');
      if (!btn) return;
      btn.addEventListener('click', async function () {
        btn.disabled = true;
        var prev = btn.textContent;
        btn.textContent = 'Opening portal…';
        try {
          var r = await fetch('/api/stripe/portal', {
            method: 'POST',
            credentials: 'same-origin',
          });
          if (!r.ok) {
            var detail = '';
            try { detail = (await r.json()).detail || ''; } catch (e) {}
            throw new Error('Could not open portal: ' + (detail || r.status));
          }
          var data = await r.json();
          window.location.href = data.url;
        } catch (e) {
          alert(e.message || 'Could not open portal. Please try again.');
          btn.disabled = false;
          btn.textContent = prev;
        }
      });
    })();
    </script>
    {% endif %}

    {# --- Import portfolio --------------------------------------------- #}
    {# Open by default because /settings#import is the deep-link target
       from the dashboard's "import a portfolio" CTA — if you arrive via
       that link the section should already be expanded. #}
    <details class="settings-section" id="import" open>
      <summary class="settings-section__head">Import portfolio (Trading 212 CSV)</summary>
      <p class="settings-section__lede">
        Export your pie from T212
        (<span class="neu">Investing &rarr; Your Pie &rarr; &middot;&middot;&middot; &rarr; Export</span>)
        and drop the CSV here. We&rsquo;ll parse it and show a preview before
        importing anywhere.
      </p>

      <div id="drop-zone" class="dz">
        <input type="file" id="file-input" name="file" accept=".csv,text/csv" hidden>
        <div class="dz__icon">▱</div>
        <div class="dz__label">Drop a T212 pie CSV here</div>
        <div class="dz__hint">or <a href="#" id="browse-link">browse</a> &middot; max 1 MB</div>
        <div class="dz__filename" id="dz-filename"></div>
      </div>

      <div id="import-preview" hidden style="margin-top:14px;"></div>
      <div id="import-result"  class="result" hidden style="margin-top:14px;"></div>
    </details>

    {# --- Referral block ---------------------------------------------- #}
    <details class="settings-section">
      <summary class="settings-section__head">Invite a friend</summary>
      <p class="settings-section__lede">
        Share your invite link. When your friend subscribes, you and
        they each get <strong>45 days of paid access</strong> credited
        to your account.
      </p>

      <div class="invite-block">
        <label class="invite-block__label">Your code</label>
        <div class="invite-block__code">{{ user.referral_code }}</div>

        <label class="invite-block__label">Invite link</label>
        <div class="invite-block__link">
          <input type="text" id="invite-url" readonly value="{{ invite_url }}">
          <button type="button" id="invite-copy">Copy</button>
        </div>
      </div>

      <div class="invite-stats">
        <div>
          <div class="invite-stats__label">Pending signups</div>
          <div class="invite-stats__value">{{ pending_count }}</div>
        </div>
        <div>
          <div class="invite-stats__label">Converted (paid)</div>
          <div class="invite-stats__value">{{ converted_count }}</div>
        </div>
        <div>
          <div class="invite-stats__label">Active credits</div>
          <div class="invite-stats__value">{{ active_credit_count }}</div>
          {% if own_credit_days %}
            <div class="settings-row__hint" style="margin-left:0;">
              +{{ own_credit_days }} day{{ '' if own_credit_days == 1 else 's' }} on your account
            </div>
          {% endif %}
        </div>
      </div>
    </details>

    {# --- Email digests block ------------------------------------------ #}
    <details class="settings-section">
      <summary class="settings-section__head">Email digests</summary>
      <p class="settings-section__lede">
        Editorial commentary delivered to your inbox. Daily for paid (Mon&ndash;Sat) plus the Sunday recap; free tier gets the Sunday recap.
      </p>

      <div class="settings-row">
        <div class="settings-row__label">Subscription</div>
        <div class="settings-row__value">
          <label style="display:block; margin-bottom:8px;">
            <input type="checkbox" id="digest-opt-in"
                   {% if user.email_digest_opt_in %}checked{% endif %}>
            Send me digests
          </label>
          <div class="settings-row__hint" style="margin-bottom:8px;">
            One-click unsubscribe in every email.
          </div>
        </div>
      </div>

      <div class="settings-row">
        <div class="settings-row__label">Reading level</div>
        <div class="settings-row__value">
          <div style="display:flex; gap:14px;">
            <label><input type="radio" name="digest-tone" value="NOVICE"
              {% if (user.digest_tone or 'INTERMEDIATE') == 'NOVICE' %}checked{% endif %}> Novice</label>
            <label><input type="radio" name="digest-tone" value="INTERMEDIATE"
              {% if (user.digest_tone or 'INTERMEDIATE') == 'INTERMEDIATE' %}checked{% endif %}> Intermediate</label>
          </div>
        </div>
      </div>

      <div class="settings-row">
        <div class="settings-row__label">Last delivery</div>
        <div class="settings-row__value settings-row__hint">
          <span id="digest-last">{% if last_email_send %}{{ last_email_send.sent_at.strftime("%Y-%m-%d %H:%M") }} UTC &mdash; {{ last_email_send.status }}{% else %}&mdash;{% endif %}</span>
        </div>
      </div>

      <div id="digest-feedback" class="settings-row__hint" style="margin-top:6px;"></div>
    </details>

    <script>
    (function () {
      const opt = document.getElementById('digest-opt-in');
      const tones = document.querySelectorAll('input[name="digest-tone"]');
      const fb = document.getElementById('digest-feedback');
      if (!opt || !fb) return;
      function patch() {
        fb.textContent = 'Saving…';
        const tone = Array.from(tones).find(t => t.checked)?.value || 'INTERMEDIATE';
        fetch('/api/settings/digest', {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ opt_in: opt.checked, tone: tone }),
        }).then(r => {
          fb.textContent = r.ok ? 'Saved.' : 'Could not save — try again.';
        }).catch(() => { fb.textContent = 'Network error.'; });
      }
      opt.addEventListener('change', patch);
      tones.forEach(t => t.addEventListener('change', patch));
    })();
    </script>

    {# --- Cloud sync block --------------------------------------------- #}
    <details class="settings-section">
      <summary class="settings-section__head">Cloud sync (encrypted)</summary>
      <p class="settings-section__lede">
        Manage the encrypted server-side copy of your portfolio. Sync is
        opted-in per import (see the Import section above).
      </p>

      {% if paid and paid.active %}
        <div id="sync-status" class="settings-row">
          <div class="settings-row__label">Status</div>
          <div class="settings-row__value">
            <span class="settings-row__hint">checking&hellip;</span>
          </div>
        </div>
        <div id="sync-actions" style="display:flex; gap:8px; flex-wrap:wrap; margin-top:8px;"></div>
        <div id="sync-feedback" class="settings-row__hint" style="margin-top:10px;"></div>
      {% else %}
        <p class="settings-row__hint">
          Available on the paid tier. Upgrade or apply an invite credit
          above to enable cloud sync.
        </p>
      {% endif %}
    </details>

    {# Future: Paddle subscription block, AI-spend ledger summary, etc. #}

    {% endif %}

  </div>
</section>

{% if user and paid and paid.active %}
<div id="sync-modal" class="modal"
     style="position:fixed;inset:0;background:rgba(0,0,0,0.45);
            display:none;align-items:center;justify-content:center;z-index:1000;">
  <div style="background:var(--panel-bg,#fff);color:var(--text,#000);
              padding:22px 26px;border-radius:8px;max-width:440px;width:90%;">
    <div class="result__head" id="sync-modal-title" style="margin-bottom:8px;">
      Enable cloud sync
    </div>
    <div id="sync-modal-body" style="font-size:13px;line-height:1.55;
                                      color:var(--muted,#666);margin-bottom:14px;">
      Choose a PIN (4&ndash;12 characters). The same PIN unlocks the
      portfolio on any device. There is no recovery if you forget it.
    </div>
    <form id="sync-modal-form" autocomplete="off">
      <label style="display:block;margin-bottom:6px;font-size:12px;">PIN</label>
      <input id="sync-pin1" type="password" inputmode="numeric"
             class="modal-input" required>
      <label style="display:block;margin-bottom:6px;font-size:12px;">Confirm PIN</label>
      <input id="sync-pin2" type="password" inputmode="numeric"
             class="modal-input" required>
      <label style="display:flex;align-items:flex-start;gap:8px;
                    font-size:12px;color:var(--muted,#666);margin:10px 0 16px;">
        <input id="sync-ack" type="checkbox" required>
        I understand that losing this PIN means I'll have to re-import my CSV.
      </label>
      <div id="sync-modal-err" class="pf-warn" hidden style="margin-bottom:10px;"></div>
      <div style="display:flex;gap:8px;justify-content:flex-end;">
        <button type="button" id="sync-modal-cancel" class="pf-secondary">Cancel</button>
        <button type="submit" id="sync-modal-submit">Enable</button>
      </div>
    </form>
  </div>
</div>

<script src="{{ url_for('static', path='/js/portfolio-sync.js') }}" defer></script>
<script>
(function () {
  function $(id) { return document.getElementById(id); }
  function esc(s) {
    return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({
      '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'
    }[c]));
  }

  document.addEventListener('DOMContentLoaded', function () {
    if (!window.CassandraSync) return;

    const statusEl = $('sync-status');
    const actionsEl = $('sync-actions');
    const feedbackEl = $('sync-feedback');
    const modal = $('sync-modal');
    const pin1 = $('sync-pin1');
    const pin2 = $('sync-pin2');
    const ack = $('sync-ack');
    const errEl = $('sync-modal-err');

    function setFeedback(msg, ok) {
      feedbackEl.style.color = ok ? 'var(--ok,#2a9d57)' : '';
      feedbackEl.textContent = msg || '';
    }
    // External callers (the Import section above) can pass a callback
    // that fires after a successful enable-and-push.
    let pendingOnSuccess = null;
    function openModal(opts) {
      pendingOnSuccess = (opts && opts.onSuccess) || null;
      modal.style.display = 'flex';
      // Focus PIN field after the layout flush so the caret lands.
      setTimeout(() => pin1.focus(), 0);
    }
    function closeModal() {
      modal.style.display = 'none';
      pin1.value = ''; pin2.value = '';
      ack.checked = false; errEl.hidden = true;
      pendingOnSuccess = null;
    }

    $('sync-modal-cancel').addEventListener('click', closeModal);
    // Backdrop click + Esc key dismiss the modal.
    modal.addEventListener('click', function (e) {
      if (e.target === modal) closeModal();
    });
    document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape' && modal.style.display !== 'none') closeModal();
    });

    $('sync-modal-form').addEventListener('submit', async function (e) {
      e.preventDefault();
      errEl.hidden = true;
      if (pin1.value !== pin2.value) {
        errEl.textContent = 'PINs do not match.';
        errEl.hidden = false; return;
      }
      if (pin1.value.length < 4) {
        errEl.textContent = 'PIN must be at least 4 characters.';
        errEl.hidden = false; return;
      }
      const pie = JSON.parse(localStorage.getItem('cassandra.pie') || 'null');
      if (!pie) {
        errEl.textContent =
          'No portfolio in this browser yet. Import a CSV first, then enable sync.';
        errEl.hidden = false; return;
      }
      try {
        await window.CassandraSync.pushSync(pie, pin1.value);
        const cb = pendingOnSuccess;
        closeModal();   // clears pendingOnSuccess
        await refresh();
        setFeedback('Cloud sync enabled. Your encrypted portfolio is stored.', true);
        if (typeof cb === 'function') {
          try { cb(); } catch (cbErr) { console.warn('sync onSuccess threw', cbErr); }
        }
      } catch (e2) {
        errEl.textContent = e2.message || 'Failed to enable sync.';
        errEl.hidden = false;
      }
    });

    async function refresh() {
      let status;
      try { status = await window.CassandraSync.getStatus(); }
      catch (e) {
        statusEl.querySelector('.settings-row__value').innerHTML =
          '<span class="pf-warn">' + esc(e.message || 'status check failed') + '</span>';
        return;
      }
      const valueEl = statusEl.querySelector('.settings-row__value');
      actionsEl.innerHTML = '';
      if (status.exists && status.orphaned) {
        // The stored blob can no longer be decrypted (server key rotated
        // since it was written). The data is permanently unrecoverable,
        // so silently clean up the dead row and re-render in the
        // standard "off" state — leaving a soft one-liner so the user
        // knows why they need to re-import.
        try { await window.CassandraSync.disableSync(); }
        catch (e) { console.warn('auto-clear stale sync failed', e); }
        setFeedback('Your previous cloud backup couldn’t be restored. Re-import your portfolio to enable cloud sync again.', true);
        await refresh();
        return;
      } else if (status.exists) {
        const when = status.updated_at
          ? new Date(status.updated_at).toISOString().replace('T', ' ').slice(0, 16) + ' UTC'
          : '—';
        valueEl.innerHTML =
          '<span class="badge badge--ok">On</span> ' +
          '<span class="settings-row__hint">last synced ' + esc(when) + '</span>';

        const disable = document.createElement('button');
        disable.type = 'button';
        disable.className = 'pf-secondary';
        disable.textContent = 'Disable sync';
        disable.addEventListener('click', async function () {
          if (!confirm('Remove your encrypted portfolio from the server? Your local copy is untouched.')) return;
          try {
            await window.CassandraSync.disableSync();
            await refresh();
            setFeedback('Cloud sync disabled. Server copy removed.', true);
          } catch (e) { setFeedback(e.message || 'Disable failed.', false); }
        });
        actionsEl.appendChild(disable);
      } else {
        valueEl.innerHTML = '<span class="badge badge--ver">Off</span>';
        // Only offer 'Enable' when there's actually a pie to encrypt;
        // otherwise the user would hit a dead-end at the modal.
        const hasPie = !!localStorage.getItem('cassandra.pie');
        if (!hasPie) {
          const hint = document.createElement('span');
          hint.className = 'settings-row__hint';
          hint.innerHTML =
            'Nothing to sync yet &mdash; ' +
            '<a href="#import">import a portfolio</a> first, then come back to enable cloud sync.';
          actionsEl.appendChild(hint);
          return;
        }
        const enable = document.createElement('button');
        enable.type = 'button';
        enable.textContent = 'Enable cloud sync';
        enable.addEventListener('click', openModal);
        actionsEl.appendChild(enable);
      }
    }

    // Hooks for the Import section to drive this modal + status row.
    window.cassandraOpenSyncModal    = openModal;
    window.cassandraRefreshSyncStatus = refresh;

    refresh();
  });
})();
</script>
{% endif %}

<script>
(function () {
  var btn = document.getElementById('invite-copy');
  var fld = document.getElementById('invite-url');
  if (!btn || !fld) return;
  btn.addEventListener('click', async function () {
    try {
      await navigator.clipboard.writeText(fld.value);
      var orig = btn.textContent;
      btn.textContent = 'Copied';
      setTimeout(function () { btn.textContent = orig; }, 1500);
    } catch (e) {
      // Fallback for older browsers: select the input.
      fld.select();
    }
  });
})();
</script>

{% if user %}
{# Import widget wiring — auto-parse on drop, preview, then commit. #}
<script src="{{ url_for('static', path='/js/portfolio.js') }}" defer></script>
<script>
(function () {
  // Server-side hint: did the user have paid privileges when the page
  // rendered? Used to decide whether to offer the 'Import & sync' button.
  // We still call CassandraSync.getStatus() at click time as the source
  // of truth, but this lets us skip rendering a button we know is dead.
  var IS_PAID = {{ 'true' if paid and paid.active else 'false' }};

  function ready(fn) {
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', fn);
    } else { fn(); }
  }

  ready(function () {
    var P = window.CassandraPortfolio;
    if (!P) return;
    var esc = P.esc, fmt = P.fmt, signed = P.signed, cls = P.cls;

    var dropZone   = document.getElementById('drop-zone');
    var fileInput  = document.getElementById('file-input');
    var browseLink = document.getElementById('browse-link');
    var filenameEl = document.getElementById('dz-filename');
    var previewEl  = document.getElementById('import-preview');
    var resultEl   = document.getElementById('import-result');
    if (!dropZone) return;

    var currentPie = null;     // most recently parsed pie, awaiting commit

    function showError(msg) {
      previewEl.hidden = true;
      resultEl.className = 'result result--err';
      resultEl.innerHTML =
        '<div class="result__head">✕ Import failed</div>' +
        '<div class="result__row">' + esc(msg) + '</div>';
      resultEl.hidden = false;
    }

    function showSuccess(headline, sub) {
      previewEl.hidden = true;
      resultEl.className = 'result result--ok';
      resultEl.innerHTML =
        '<div class="result__head">' + esc(headline) + '</div>' +
        (sub ? '<div class="result__row">' + sub + '</div>' : '') +
        '<div class="result__row" style="margin-top:14px;">' +
          '<a href="/">Open dashboard →</a>' +
        '</div>';
      resultEl.hidden = false;
    }

    function renderPreview(pie) {
      currentPie = pie;
      resultEl.hidden = true;

      var t = pie.totals || {};
      var rows = (pie.positions || []).map(function (p) {
        var invested = (p.avg_cost != null && p.qty != null) ? p.avg_cost * p.qty : null;
        return '<tr>' +
          '<td class="label">' + esc(p.yahoo_ticker || p.t212_slice || '') + '</td>' +
          '<td>' + esc(p.name || '') + '</td>' +
          '<td class="num">' + fmt(p.qty, { maximumFractionDigits: 6 }) + '</td>' +
          '<td class="num neu">' + fmt(p.avg_cost) + '</td>' +
          '<td class="num">' + fmt(invested) + '</td>' +
          '</tr>';
      }).join('');

      var warnings = (pie.warnings || []).map(function (w) {
        return '<div class="result__warn">' + esc(w) + '</div>';
      }).join('');

      var syncBtn = IS_PAID
        ? ('<div class="import-choice">' +
             '<button type="button" id="commit-sync">Import &amp; sync to cloud</button>' +
             '<div class="settings-row__hint">' +
               'Also stores an <strong>encrypted</strong> copy on the server, ' +
               'restorable on any device with your PIN. Only you can decrypt ' +
               'it &mdash; losing the PIN means losing the backup.' +
             '</div>' +
           '</div>')
        : ('<div class="import-choice">' +
             '<button type="button" disabled>Import &amp; sync to cloud</button>' +
             '<div class="settings-row__hint">' +
               'Encrypted cloud backup is available on the paid tier.' +
             '</div>' +
           '</div>');

      previewEl.innerHTML =
        '<div class="result result--ok" style="margin:0;">' +
          '<div class="result__head">' +
            '▸ Preview: <strong>' + esc(pie.pie_name || 'pie') + '</strong>' +
          '</div>' +
          '<div class="result__grid">' +
            '<div><div class="k">Positions</div><div class="v">' + (pie.positions || []).length + '</div></div>' +
            '<div><div class="k">Invested</div><div class="v">' + fmt(t.invested) + '</div></div>' +
            '<div><div class="k">Value</div><div class="v">' + fmt(t.value) + '</div></div>' +
            '<div><div class="k">Result</div><div class="v ' + cls(t.result) + '">' + signed(t.result) + '</div></div>' +
          '</div>' +
          warnings +
          (rows
            ? '<div style="max-height:280px;overflow:auto;margin-top:12px;">' +
                '<table class="dense">' +
                  '<thead><tr>' +
                    '<th>Ticker</th><th>Name</th>' +
                    '<th class="num">Qty</th>' +
                    '<th class="num">Avg</th>' +
                    '<th class="num">Invested</th>' +
                  '</tr></thead>' +
                  '<tbody>' + rows + '</tbody>' +
                '</table>' +
              '</div>'
            : ''
          ) +
          '<div class="import-actions">' +
            '<div class="import-choice">' +
              '<button type="button" id="commit-local">Import to this browser</button>' +
              '<div class="settings-row__hint">' +
                'Saved to this browser only. No server-side copy of your holdings.' +
              '</div>' +
            '</div>' +
            syncBtn +
            '<div style="flex-basis:100%;">' +
              '<button type="button" id="commit-cancel" class="pf-secondary">' +
                'Cancel</button>' +
            '</div>' +
          '</div>' +
        '</div>';

      previewEl.hidden = false;

      document.getElementById('commit-local').addEventListener('click', commitLocal);
      document.getElementById('commit-cancel').addEventListener('click', resetUploader);
      var syncEl = document.getElementById('commit-sync');
      if (syncEl) syncEl.addEventListener('click', commitSync);
    }

    function commitLocal() {
      if (!currentPie) return;
      P.savePie(currentPie);
      showSuccess('▸ Imported to this browser.',
        'Pie kept locally; no server-side copy.');
      currentPie = null;
    }

    async function commitSync() {
      if (!currentPie) return;
      // Save locally first so the cloud-sync flow uses the freshly-imported
      // pie (the enable-PIN modal in this same page reads from localStorage).
      P.savePie(currentPie);
      var S = window.CassandraSync;
      if (!S) { showError('Cloud sync module not loaded.'); return; }

      var status;
      try { status = await S.getStatus(); }
      catch (e) { showError('Could not check sync status: ' + (e.message || e)); return; }

      if (!status.paid) {
        showError('Cloud sync requires the paid tier.');
        return;
      }

      if (status.exists) {
        // Already enabled — try a direct push using the cached session
        // key. If no key is cached (fresh browser session), this throws,
        // and we fall back to the enable-PIN modal so the user can
        // re-enter their PIN.
        try {
          await S.pushSync(currentPie, null);
          showSuccess('▸ Imported and synced.',
            'Encrypted copy updated on the server.');
          currentPie = null;
          if (window.cassandraRefreshSyncStatus) window.cassandraRefreshSyncStatus();
          return;
        } catch (e) {
          // Fall through to modal so the user can re-auth with their PIN.
          console.warn('direct push failed, falling back to PIN modal', e);
        }
      }

      // !status.exists OR cached-key push failed → use the modal.
      if (window.cassandraOpenSyncModal) {
        window.cassandraOpenSyncModal({
          onSuccess: function () {
            showSuccess('▸ Imported and synced.',
              'Cloud sync is now enabled and the pie is stored encrypted.');
            currentPie = null;
          },
        });
      } else {
        showError('Cloud sync UI unavailable on this page. ' +
                  'Use the Cloud sync section below to enable.');
      }
    }

    function resetUploader() {
      currentPie = null;
      previewEl.hidden = true;
      previewEl.innerHTML = '';
      resultEl.hidden = true;
      filenameEl.textContent = '';
      fileInput.value = '';
    }

    async function parseFile(file) {
      filenameEl.textContent = file.name + ' (' + Math.round(file.size / 1024) + ' KB) — parsing…';
      previewEl.hidden = true;
      resultEl.hidden = true;
      try {
        var pie = await P.parseCsv(file);
        renderPreview(pie);
        filenameEl.textContent = file.name + ' (' + Math.round(file.size / 1024) + ' KB)';
      } catch (e) {
        filenameEl.textContent = file.name + ' (failed)';
        showError(e.message || 'Unknown error');
      }
    }

    browseLink.addEventListener('click', function (e) { e.preventDefault(); fileInput.click(); });
    fileInput.addEventListener('change', function () {
      if (fileInput.files[0]) parseFile(fileInput.files[0]);
    });

    ['dragenter', 'dragover'].forEach(function (ev) {
      dropZone.addEventListener(ev, function (e) {
        e.preventDefault(); e.stopPropagation();
        dropZone.classList.add('dz--over');
      });
    });
    ['dragleave', 'drop'].forEach(function (ev) {
      dropZone.addEventListener(ev, function (e) {
        e.preventDefault(); e.stopPropagation();
        dropZone.classList.remove('dz--over');
      });
    });
    dropZone.addEventListener('drop', function (e) {
      var f = e.dataTransfer.files && e.dataTransfer.files[0];
      if (f) parseFile(f);
    });
    dropZone.addEventListener('click', function (e) {
      if (e.target.tagName !== 'A') fileInput.click();
    });
  });
})();
</script>
{% endif %}
{% endblock %}
