// Billing / entitlement layer (Free vs Solo).
//
// Exposes on window:
//   ppGetEntitlement() / ppRefreshEntitlement() — read the user's plan from the
//     `subscriptions` table (cached on window.__entitlement; fires `pp-entitlement`).
//   ppIsSolo() — sync boolean from the cache.
//   useEntitlement() — React hook returning the reactive entitlement.
//   ppStartCheckout('month'|'year') — Stripe Checkout via the edge function.
//   ppOpenPortal() — Stripe Customer Portal.
//   ppOpenUpgrade(reason) — open the global UpgradeModal from anywhere.
//
// Wrapped in an IIFE (shared global lexical scope across the Babel <script>s).
(function () {
  const { useState, useEffect } = React;

  // Fallback display price — shown only on the very first paint of a brand-new
  // browser, before get-prices resolves. It's overridden by the live Stripe
  // amount (fetched + cached below), so keep it matching the current Stripe price
  // to avoid any visible change on open.
  const SOLO_PRICE = { month: '€6 / mo', year: '€50 / yr' };

  const FREE_ENT = { plan: 'free', status: 'none', interval: null, solo: false };

  // Live Solo price cache. get-prices returns the real Stripe amount; we cache it
  // in localStorage so the plans modal paints the correct value immediately on
  // every later load (no hard-coded-then-fetched flicker), then refresh on open.
  function ppReadCachedPrices() {
    try {
      const o = JSON.parse(localStorage.getItem('pp_solo_prices') || 'null');
      if (o && o.month && o.year) return { month: o.month, year: o.year };
    } catch (e) {}
    return null;
  }
  function ppWriteCachedPrices(p) {
    try { localStorage.setItem('pp_solo_prices', JSON.stringify(p)); } catch (e) {}
  }
  if (!window.__soloPrices) { const _cached = ppReadCachedPrices(); if (_cached) window.__soloPrices = _cached; }

  // ──────────────────────────────── entitlement read
  async function ppGetEntitlement(force) {
    if (window.__entitlement && !force) return window.__entitlement;
    const sb = window.supabaseClient;
    let ent = { ...FREE_ENT };
    try {
      if (sb) {
        const { data: { session } } = await sb.auth.getSession();
        if (session) {
          const { data, error } = await sb
            .from('subscriptions')
            .select('plan,status,interval,current_period_end')
            .eq('user_id', session.user.id)
            .maybeSingle();
          const row = (!error && data) ? data : null;
          const solo = !!row && row.plan === 'solo' && (row.status === 'active' || row.status === 'trialing');
          ent = {
            plan: solo ? 'solo' : 'free',
            status: row ? row.status : 'none',
            interval: row ? row.interval : null,
            current_period_end: row ? row.current_period_end : null,
            solo,
          };
        }
      }
    } catch (e) { /* default to free */ }
    window.__entitlement = ent;
    try { window.dispatchEvent(new CustomEvent('pp-entitlement', { detail: ent })); } catch (e) {}
    return ent;
  }
  const ppRefreshEntitlement = () => ppGetEntitlement(true);
  const ppIsSolo = () => !!(window.__entitlement && window.__entitlement.solo);

  function useEntitlement() {
    const [ent, setEnt] = useState(window.__entitlement || FREE_ENT);
    useEffect(() => {
      let mounted = true;
      ppGetEntitlement().then((e) => { if (mounted) setEnt(e); });
      const onChange = (e) => { if (mounted) setEnt(e.detail); };
      window.addEventListener('pp-entitlement', onChange);
      let sub;
      const sb = window.supabaseClient;
      if (sb) { const r = sb.auth.onAuthStateChange(() => ppRefreshEntitlement()); sub = r.data; }
      return () => {
        mounted = false;
        window.removeEventListener('pp-entitlement', onChange);
        if (sub && sub.subscription) sub.subscription.unsubscribe();
      };
    }, []);
    return ent;
  }

  // ──────────────────────────────── checkout / portal (edge functions)
  async function ppStartCheckout(interval) {
    const sb = window.supabaseClient;
    if (!sb) { alert('Cloud sync is not configured.'); return; }
    const { data: { session } } = await sb.auth.getSession();
    if (!session) { if (window.__jumpOpenAuth) window.__jumpOpenAuth(); return; }
    try {
      const { data, error } = await sb.functions.invoke('create-checkout-session', { body: { interval: interval || 'year' } });
      if (error) throw error;
      if (data && data.url) window.location.href = data.url;
      else throw new Error('No checkout URL returned');
    } catch (e) { alert('Could not start checkout: ' + (e.message || e)); }
  }
  async function ppOpenPortal() {
    const sb = window.supabaseClient;
    if (!sb) return;
    const { data: { session } } = await sb.auth.getSession();
    if (!session) { if (window.__jumpOpenAuth) window.__jumpOpenAuth(); return; }
    try {
      const { data, error } = await sb.functions.invoke('create-portal-session', { body: {} });
      if (error) throw error;
      if (data && data.url) window.location.href = data.url;
    } catch (e) { alert('Could not open the billing portal: ' + (e.message || e)); }
  }

  // ──────────────────────────────── UpgradeModal
  function PlansModal({ reason, onClose }) {
    const ent = useEntitlement();
    const [interval, setIntervalSel] = useState('month');
    const [prices, setPrices] = useState(window.__soloPrices || SOLO_PRICE);
    const isSolo = !!ent.solo;
    const per = interval === 'year' ? '/yr' : '/mo';

    // Pull the real Solo prices from Stripe (get-prices function) so the displayed
    // amount is never a hard-coded guess. Cached on window so it fetches once.
    useEffect(() => {
      const sb = window.supabaseClient;
      if (!sb) return;
      let alive = true;
      (async () => {
        try {
          const { data, error } = await sb.functions.invoke('get-prices', { body: {} });
          if (error || !data) return;
          const next = {
            month: (data.month && data.month.display) || SOLO_PRICE.month,
            year: (data.year && data.year.display) || SOLO_PRICE.year,
          };
          window.__soloPrices = next;
          ppWriteCachedPrices(next);
          if (alive) setPrices(next);
        } catch (e) {}
      })();
      return () => { alive = false; };
    }, []);

    const TIERS = [
      { key: 'free', name: 'Free', price: { month: '$0', year: '$0' },
        features: ['5 storyboards', '60 frames per storyboard', 'Watermarked PDF export'] },
      { key: 'solo', name: 'Solo', price: prices, highlight: true,
        features: ['Unlimited storyboards', 'Unlimited frames', 'Clean PDF export', 'Client review links + comments'] },
      { key: 'pro', name: 'Pro', soon: true,
        features: ['Everything in Solo', '2 editor seats'] },
      { key: 'team', name: 'Team', soon: true,
        features: ['Everything in Pro', '10 users'] },
    ];

    const renderCta = (t) => {
      if (t.soon) return <button className="btn plan-cta" disabled>Coming soon</button>;
      if (t.key === 'free') {
        return isSolo
          ? <button className="btn plan-cta" onClick={ppOpenPortal}>Downgrade</button>
          : <button className="btn plan-cta" disabled>Current plan</button>;
      }
      return isSolo
        ? <button className="btn plan-cta" onClick={ppOpenPortal}>Manage billing</button>
        : <button className="btn btn-primary plan-cta" onClick={() => ppStartCheckout(interval)}>Upgrade</button>;
    };

    return ReactDOM.createPortal(
      <div className="modal-backdrop" onClick={onClose}>
        <div className="modal plans-modal" onClick={(e) => e.stopPropagation()}>
          <button className="plans-close" onClick={onClose} aria-label="Close">×</button>
          <h2>Plans</h2>
          {reason
            ? <p className="modal-sub plans-reason">{reason}</p>
            : <p className="modal-sub">Choose the plan that fits.{isSolo ? " You're currently on Solo." : ''}</p>}

          <div className="seg billing-toggle" role="group" aria-label="Billing interval">
            <button className={interval === 'month' ? 'active' : ''} onClick={() => setIntervalSel('month')}>Monthly</button>
            <button className={interval === 'year' ? 'active' : ''} onClick={() => setIntervalSel('year')}>
              Annual <span className="save-pill">save ~2 months</span>
            </button>
          </div>

          <div className="plans-grid">
            {TIERS.map((t) => {
              const current = (isSolo && t.key === 'solo') || (!isSolo && t.key === 'free');
              return (
                <div key={t.key} className={`plan-col ${t.highlight ? 'plan-col-solo' : ''} ${current ? 'plan-col-current' : ''}`}>
                  <div className="plan-name">{t.name}{current ? <span className="plan-current-tag">Current</span> : null}</div>
                  <div className="plan-price">
                    {t.soon ? <span className="plan-soon">—</span> : <>{t.price[interval]}{t.key !== 'free' ? <span className="plan-per"> {per}</span> : null}</>}
                  </div>
                  <ul>{t.features.map((f, i) => <li key={i} className={t.key === 'solo' && i === 3 ? 'feat-hero' : ''}>{f}</li>)}</ul>
                  {renderCta(t)}
                </div>
              );
            })}
          </div>
        </div>
      </div>,
      document.body
    );
  }

  function ppOpenUpgrade(reason) {
    try { window.dispatchEvent(new CustomEvent('pp-open-upgrade', { detail: { reason: reason || '' } })); } catch (e) {}
  }
  function ppOpenPlans() { ppOpenUpgrade(''); }

  // Self-mounting host so ppOpenUpgrade() works from any view, plus it handles
  // the post-checkout return (?checkout=success → refresh entitlement).
  function UpgradeHost() {
    const [open, setOpen] = useState(false);
    const [reason, setReason] = useState('');
    useEffect(() => {
      const onOpen = (e) => { setReason((e.detail && e.detail.reason) || ''); setOpen(true); };
      window.addEventListener('pp-open-upgrade', onOpen);
      try {
        const p = new URLSearchParams(location.search);
        if (p.get('checkout') === 'success') {
          ppRefreshEntitlement();
          p.delete('checkout');
          const qs = p.toString();
          history.replaceState(null, '', location.pathname + (qs ? '?' + qs : ''));
        }
      } catch (e) {}
      return () => window.removeEventListener('pp-open-upgrade', onOpen);
    }, []);
    if (!open) return null;
    return <PlansModal reason={reason} onClose={() => setOpen(false)} />;
  }

  function mountUpgradeHost() {
    try {
      let el = document.getElementById('pp-upgrade-host');
      if (!el) { el = document.createElement('div'); el.id = 'pp-upgrade-host'; document.body.appendChild(el); }
      ReactDOM.createRoot(el).render(<UpgradeHost />);
    } catch (e) { console.warn('upgrade host mount failed', e); }
  }
  if (document.body) mountUpgradeHost();
  else window.addEventListener('DOMContentLoaded', mountUpgradeHost);

  Object.assign(window, {
    ppGetEntitlement, ppRefreshEntitlement, ppIsSolo, useEntitlement,
    ppStartCheckout, ppOpenPortal, ppOpenUpgrade, ppOpenPlans, PlansModal,
  });
})();
