<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <meta name="theme-color" content="#0EA5E9" />
  <title>Billing — takedowns</title>
  <link rel="stylesheet" href="/public/css/glass.css?v=2-light" />
</head>
<body>
  <div class="app">
    <aside>
      <a href="/" class="brand" aria-label="takedowns home"><img src="/public/og/logo-mark.png" alt="" width="28" height="28" /><span class="brand-wordmark">takedowns<small>by vesamuni</small></span></a>
      <nav>
        <a href="/dashboard/">Dashboard</a>
        <a href="/cases/">Cases</a>
        <a href="/scan/">Scan</a>
        <a href="/takedown/">Takedowns</a>
        <a href="/billing/" class="active">Billing</a>
        <a href="/admin/" data-admin-only class="hidden">Admin</a>
        <a href="#" id="logout">Sign out</a>
      </nav>
    </aside>
    <main>
      <header class="topbar">
        <h1>Billing</h1>
        <div class="user-pill">
          <span id="siteHealthDot" class="site-health-dot unknown" title="checking…"></span>
        </div>
      </header>
      <div id="flash"></div>

      <section class="panel" id="currentPanel">
        <h2>Current plan</h2>
        <div id="current"></div>
      </section>

      <!-- Credit packs live in their own panel so they're visible even
           to users who already have a subscription. -->
      <section class="panel" id="creditPanel" style="display:none">
        <h2>One-time credit packs</h2>
        <p class="muted">Buy credits that never expire. They stack on top of whatever plan you have.</p>
        <div class="cards" id="creditPacks"></div>
      </section>

      <section class="panel">
        <h2>Choose a plan</h2>

        <!-- Monthly / annual toggle — drives the price labels and the
             interval param sent to /billing/checkout. -->
        <div class="billing-toggle" role="tablist" aria-label="Billing interval">
          <button type="button" class="toggle-opt active" data-interval="month" role="tab" aria-selected="true">Monthly</button>
          <button type="button" class="toggle-opt"        data-interval="year"  role="tab" aria-selected="false">
            Annual <span class="badge save">Save ~17%</span>
          </button>
        </div>

        <div class="cards" id="plans"></div>

        <!-- Agency-only seat picker — hidden until Agency is selected.
             The minimum is enforced server-side; the input is just
             convenience. -->
        <div id="seatPicker" class="hidden">
          <label for="seats"><strong>Team seats</strong> (Agency)</label>
          <div class="flex" style="gap:.5rem;align-items:center">
            <button type="button" id="seatsDown" class="secondary">−</button>
            <input id="seats" type="number" min="3" max="50" step="1" value="3" style="width:5rem;text-align:center" />
            <button type="button" id="seatsUp" class="secondary">+</button>
            <span id="seatTotal" class="muted"></span>
          </div>
          <div class="muted" style="font-size:.85rem;margin-top:.25rem">
            Each seat = 25 active cases · 500 scans · 250 takedowns / month.
          </div>
        </div>
      </section>

      <p class="muted" style="font-size:.85rem">
        Prices in USD. Tax (VAT / GST / sales tax) is calculated by Stripe
        based on your billing address. Promo codes can be entered on the
        next step.
      </p>
    </main>
  </div>

  <script>
    function csrf(){const m=document.cookie.match(/(?:^|; )ncsrf=([^;]+)/);return m?m[1]:'';}
    async function api(p,o={}){const r=await fetch(p,{...o,headers:{'content-type':'application/json','x-csrf-token':csrf(),...(o.headers||{})}});if(r.status===401){location.href='/login?next='+encodeURIComponent(location.pathname);return null;}return r.json().catch(()=>({}));}
    function esc(s){return String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}
    function flash(t,m){document.getElementById('flash').innerHTML=`<div class="flash ${esc(t)}">${esc(m)}</div>`;setTimeout(()=>document.getElementById('flash').innerHTML='',6000);}

    // ---- State ---------------------------------------------------
    let interval = 'month';      // 'month' | 'year'
    let seats = 3;               // Agency quantity
    let selectedPlan = null;     // last clicked plan key
    let me = null;
    let plansData = [];

    function fmtPrice(cents, iv) {
      if (!cents) return '$0';
      return '$' + (cents/100).toFixed(0) + (iv === 'year' ? '/yr' : (iv === 'one_time' ? '' : '/mo'));
    }

    function computeLineTotal(plan, iv, qty) {
      const unit = (iv === 'year' ? plan.price_cents_annual : plan.price_cents) || 0;
      const q = plan.per_seat ? Math.max(1, qty) : 1;
      return unit * q;
    }

    function renderPlans(plans) {
      const subs = plans.filter(p => p.kind !== 'credit_pack');
      const cards = document.getElementById('plans');
      cards.innerHTML = subs.map(p => {
        const unit = interval === 'year' ? (p.price_cents_annual || 0) : p.price_cents;
        const isCurrent = p.key === me.user.plan;
        const isFree = !p.price_cents;
        const perSeatLabel = p.per_seat ? '/seat' : '';
        const unitLabel = interval === 'year' ? '/yr' : '/mo';
        const showLimit = p.per_seat
          ? `${p.cases_limit_per_seat || 0} cases · ${p.scans_limit_per_seat || 0} scans · ${p.takedowns_limit_per_seat || 0} takedowns <em>/ seat</em>`
          : `${p.cases_limit} cases · ${p.scans_limit} scans · ${p.takedowns_limit} takedowns`;
        return `
        <div class="card ${isCurrent ? 'ok' : ''}" data-plan-card="${esc(p.key)}">
          <h3>${esc(p.name)}${p.per_seat ? ' <span class="badge">per-seat</span>' : ''}</h3>
          <div class="v">${unit ? '$' + (unit/100).toFixed(0) : '$0'}<span class="muted" style="font-size:.9rem">${perSeatLabel}${unitLabel}</span></div>
          <div class="sub">${showLimit}</div>
          <ul class="muted" style="font-size:.85rem;padding-left:1rem">
            ${(p.api_access ? '<li>REST API access</li>' : '')}
            <li>Up to ${p.users_limit} user${p.users_limit === 1 ? '' : 's'}</li>
          </ul>
          ${isCurrent
            ? '<button disabled class="mt-1">Current</button>'
            : (isFree
                ? '<button class="secondary mt-1" disabled>Free</button>'
                : `<button class="mt-1" data-plan="${esc(p.key)}">Choose ${esc(p.name)}</button>`)}
        </div>`;
      }).join('');
      document.querySelectorAll('[data-plan]').forEach(b => {
        b.onclick = () => startCheckout(b.dataset.plan);
      });
      updateSeatPicker();
    }

    function renderCreditPacks(plans) {
      const packs = plans.filter(p => p.kind === 'credit_pack');
      if (!packs.length) {
        document.getElementById('creditPanel').style.display = 'none';
        return;
      }
      document.getElementById('creditPanel').style.display = '';
      document.getElementById('creditPacks').innerHTML = packs.map(p => `
        <div class="card">
          <h3>${esc(p.name)}</h3>
          <div class="v">$${(p.price_cents/100).toFixed(0)}<span class="muted" style="font-size:.9rem"> one-time</span></div>
          <div class="sub">${esc(p.grants ? p.grants.scans : 0)} scan credits · ${esc(p.grants ? p.grants.takedowns : 0)} takedown credits</div>
          <ul class="muted" style="font-size:.85rem;padding-left:1rem">
            ${(p.features || []).map(f => `<li>${esc(f)}</li>`).join('')}
          </ul>
          <button class="mt-1" data-plan="${esc(p.key)}">Buy credits</button>
        </div>
      `).join('');
      // Re-wire choose buttons for credit packs (selector matches both panels).
      document.querySelectorAll('[data-plan]').forEach(b => {
        b.onclick = () => startCheckout(b.dataset.plan);
      });
    }

    function updateSeatPicker() {
      const picker = document.getElementById('seatPicker');
      const show = selectedPlan === 'agency';
      picker.classList.toggle('hidden', !show);
      const plan = plansData.find(p => p.key === 'agency');
      if (!plan) return;
      const total = computeLineTotal(plan, interval, seats);
      const seatsLabel = seats === 1 ? 'seat' : 'seats';
      document.getElementById('seatTotal').textContent =
        `${seats} ${seatsLabel} × ${fmtPrice(interval === 'year' ? plan.price_cents_annual : plan.price_cents, interval)} = $${(total/100).toFixed(0)}${interval === 'year' ? '/yr' : '/mo'}`;
    }

    async function startCheckout(planKey) {
      selectedPlan = planKey;
      updateSeatPicker();
      const planDef = plansData.find(p => p.key === planKey);
      const isCreditPack = planDef && planDef.kind === 'credit_pack';
      const body = { plan: planKey };
      if (!isCreditPack) body.interval = interval;
      if (planDef && planDef.per_seat) body.quantity = seats;
      const r = await api('/billing/checkout', { method: 'POST', body: JSON.stringify(body) });
      if (r && r.url) location.href = r.url;
      else flash('err', (r && (r.message || r.error)) || 'Checkout failed');
    }

    // ---- Interval toggle -----------------------------------------
    function setInterval(iv) {
      interval = iv;
      document.querySelectorAll('.toggle-opt').forEach(b => {
        const active = b.dataset.interval === iv;
        b.classList.toggle('active', active);
        b.setAttribute('aria-selected', active ? 'true' : 'false');
      });
      renderPlans(plansData);
    }

    // ---- Init ----------------------------------------------------
    async function load() {
      const [meResp, plansResp] = await Promise.all([api('/billing/me'), api('/billing/plans')]);
      if (!meResp || !plansResp) return;
      me = meResp;
      plansData = plansResp.plans;
      if (me.billing_interval === 'year') setInterval('year');
      const plan = me.plan;
      const iv = me.billing_interval || 'month';
      const seatsInfo = plan.per_seat && me.seats > 1 ? ` · ${me.seats} seats` : '';
      const intervalLabel = iv === 'year' ? 'billed annually' : (iv === 'month' ? 'billed monthly' : '');
      const extra = (me.extra_scans || me.extra_takedowns) ? `
        <div class="muted" style="margin-top:.5rem">
          <strong>Credits:</strong>
          ${me.extra_scans || 0} scan · ${me.extra_takedowns || 0} takedown (never expire)
        </div>` : '';
      document.getElementById('current').innerHTML = `
        <div class="flex between">
          <div>
            <h3 style="margin:0">${esc(plan.name)}${seatsInfo}</h3>
            <div class="muted">${esc(plan.price_cents ? fmtPrice(plan.price_cents, iv) + ' ' + intervalLabel : 'Free')}</div>
            <ul class="muted" style="margin:.5rem 0 0 0;padding-left:1rem">
              ${plan.features.map(f => `<li>${esc(f)}</li>`).join('')}
            </ul>
            ${extra}
            ${me.payment_failed ? '<div class="flash err mt-1">Payment failed. Please update your card.</div>' : ''}
          </div>
          <div class="flex">
            ${me.user.stripe_customer_id ? '<button class="secondary" id="portalBtn">Manage subscription</button>' : ''}
          </div>
        </div>`;
      if (me.user.stripe_customer_id) {
        document.getElementById('portalBtn').onclick = async () => {
          const r = await api('/billing/portal', { method: 'POST' });
          if (r && r.url) location.href = r.url;
        };
      }
      const params = new URLSearchParams(location.search);
      if (params.get('status') === 'success') flash('ok', 'Purchase complete — credits are active.');
      if (params.get('status') === 'cancel') flash('info', 'Checkout cancelled.');

      renderPlans(plansData);
      renderCreditPacks(plansData);
    }

    document.querySelectorAll('.toggle-opt').forEach(b => {
      b.onclick = () => setInterval(b.dataset.interval);
    });
    document.getElementById('seatsDown').onclick = () => {
      const input = document.getElementById('seats');
      const next = Math.max(parseInt(input.min || '1', 10), (parseInt(input.value, 10) || 1) - 1);
      input.value = next; seats = next; updateSeatPicker();
    };
    document.getElementById('seatsUp').onclick = () => {
      const input = document.getElementById('seats');
      const next = Math.min(parseInt(input.max || '99', 10), (parseInt(input.value, 10) || 1) + 1);
      input.value = next; seats = next; updateSeatPicker();
    };
    document.getElementById('seats').addEventListener('input', (e) => {
      const v = parseInt(e.target.value, 10);
      if (Number.isFinite(v)) { seats = v; updateSeatPicker(); }
    });

    document.getElementById('logout').onclick = async (e) => { e.preventDefault(); await api('/auth/logout', { method: 'POST' }); location.href = '/'; };
    load();
  </script>
  <script src="/public/js/siteHealth.js" defer></script>
  <style>
    .billing-toggle { display:inline-flex; border:1px solid #cbd5e1; border-radius:8px; overflow:hidden; margin-bottom:1rem; }
    .billing-toggle .toggle-opt { background:transparent; border:0; padding:.5rem 1rem; cursor:pointer; }
    .billing-toggle .toggle-opt.active { background:#0EA5E9; color:#fff; }
    .billing-toggle .badge.save { background:#16a34a; color:#fff; padding:.1rem .4rem; border-radius:4px; font-size:.7rem; margin-left:.25rem; }
    .badge { background:#e0f2fe; color:#0369a1; padding:.1rem .4rem; border-radius:4px; font-size:.7rem; vertical-align:middle; }
  </style>
</body>
</html>
