// DISCOUNT TOAST NOTIFICATIONS
// Fires a toast (same chrome as the existing waitlist toast, blue accent
// instead of orange) when the user activates any discount. Six discount
// types are watched:
//   1. Multi-service (2+ services in cart, tiered 5/15/25/35/45%)
//   2. Commitment (6mo = -20%, 12mo = -40% per service)
//   3. Pay upfront (-10% per service when toggled on)
//   4. Bring Your Own List addon (-15% retainer per service)
//   5. Promo code (variable %, applied via the discount-code input)
//   6. Agency partner intent (-15% own-agency / -40% white-label, all tiers)
//
// Detection: maintains a useRef of "previous discount state" and compares on
// each render. A toast fires when a discount transitions from inactive to
// active OR upgrades to a higher band (e.g. 6mo to 12mo).
//
// Hydration guard: silently snapshots state during the first 1500ms after
// mount. Without this, every page refresh fires toasts for ALL currently-
// active discounts (because the initial render looks like a "fresh
// activation" against the default-empty prev state).
//
// Toasts are stackable and dismiss on X-click only.

(function () {
  function MsdTier(serviceCount) {
    // 2026-05-30: aligned to the live two-tier rule (2 services = 5%, 3+ = 10%).
    if (serviceCount >= 3) return { n: 3, pct: 10, label: '3 or more services' };
    if (serviceCount === 2) return { n: 2, pct: 5, label: '2 services' };
    return { n: 0, pct: 0, label: '' };
  }

  function svcName(svcId) {
    const svc = (window.SERVICES || []).find(s => s.id === svcId);
    return svc ? svc.name : svcId;
  }

  function commitPctFor(commitMonths) {
    if (commitMonths === 12) return 40;
    if (commitMonths === 6) return 20;
    return 0;
  }

  function DiscountToastManager({ state }) {
    const { useRef, useState, useEffect } = React;
    const [toasts, setToasts] = useState([]);
    const prev = useRef({
      msdTier: 0,
      commitByService: {},
      payUpfrontByService: {},
      byolByService: {},
      promoCode: null,
      agencyMult: 1,
      intentId: null,
      ready: false,
      mountedAt: Date.now(),
    });
    /* 2026-05-29: track auto-dismiss timers so we can clear them on
       unmount (avoids "setState on unmounted component" warnings if the
       host page navigates away within 3s of a toast firing). */
    const dismissTimers = useRef([]);

    /* 2026-05-29 v2: two-step dismiss. Mark `leaving: true` first so the
       CSS exit animation (opacity → 0, slide right) can play; then 320ms
       later actually remove the toast from the array. Reused by both
       the auto-dismiss timer and the X-click handler. */
    const beginLeaving = (id) => {
      setToasts(t => t.map(x => x.id === id ? { ...x, leaving: true } : x));
      const removeTimer = setTimeout(() => {
        setToasts(t => t.filter(x => x.id !== id));
      }, 320);
      dismissTimers.current.push(removeTimer);
    };

    /* Public dismiss: alias for beginLeaving (kept as `dismiss` so the
       existing close-button onClick keeps working unchanged). */
    const dismiss = (id) => beginLeaving(id);

    const push = (title, body, meta) => {
      const id = Date.now() + Math.random();
      setToasts(t => {
        // De-dupe identical title within the current visible stack
        if (t.some(x => x.title === title)) return t;
        return [...t, { id, title, body, meta, leaving: false }];
      });
      /* 2026-05-29 v2: auto-dismiss after 5s (was 3s). Scheduled
         unconditionally — if the dedup guard rejected the push, the
         timer fires a harmless no-op since no toast matches the new id. */
      const timer = setTimeout(() => beginLeaving(id), 5000);
      dismissTimers.current.push(timer);
    };

    /* Cleanup any pending auto-dismiss + remove timers on unmount. */
    useEffect(() => {
      return () => {
        dismissTimers.current.forEach(clearTimeout);
        dismissTimers.current = [];
      };
    }, []);

    useEffect(() => {
      if (!state || !state.selections) return;
      const selections = state.selections || {};
      const svcIds = Object.keys(selections);
      const p = prev.current;

      // Hydration guard: any state change within the first 1500ms after mount
      // is treated as initial hydration burst (localStorage rehydration +
      // StrictMode double-effects) and snapshots silently without firing.
      const elapsedSinceMount = Date.now() - p.mountedAt;
      if (!p.ready || elapsedSinceMount < 1500) {
        p.msdTier = MsdTier(svcIds.length).n;
        for (const sid of svcIds) {
          const sel = selections[sid];
          if (!sel) continue;
          p.commitByService[sid] = sel.commitMonths || 3;
          p.payUpfrontByService[sid] = !!sel.payUpfront;
          p.byolByService[sid] = Array.isArray(sel.addons) && sel.addons.includes('byol');
        }
        p.promoCode = state.promoApplied?.code || null;
        p.agencyMult = window.getAgencyMultiplier ? window.getAgencyMultiplier(state) : 1;
        p.ready = true;
        return;
      }

      // 1. Multi-service tier
      const msd = MsdTier(svcIds.length);
      if (msd.n > p.msdTier && msd.pct > 0) {
        push(
          'Multi-service discount unlocked',
          msd.pct + '% off all service retainers for ' + msd.label + ' in your plan.',
          'Auto-applied to your monthly total.'
        );
      }
      p.msdTier = msd.n;

      // 2. Commitment per service
      for (const sid of svcIds) {
        const sel = selections[sid];
        if (!sel) continue;
        const cur = sel.commitMonths || 3;
        const prevCommit = p.commitByService[sid] || 3;
        const curPct = commitPctFor(cur);
        const prevPct = commitPctFor(prevCommit);
        if (curPct > prevPct && curPct > 0) {
          push(
            cur + '-month commitment locked in',
            curPct + '% off ' + svcName(sid) + ' for the length of your contract.',
            'Applies until the commitment ends.'
          );
        }
        p.commitByService[sid] = cur;
      }

      // 3. Pay upfront per service
      for (const sid of svcIds) {
        const sel = selections[sid];
        if (!sel) continue;
        const cur = !!sel.payUpfront;
        const wasPrev = !!p.payUpfrontByService[sid];
        if (cur && !wasPrev) {
          push(
            'Pay upfront discount applied',
            '10% off ' + svcName(sid) + ' when you pay your contract upfront.',
            'Toggle off in the service card to revert.'
          );
        }
        p.payUpfrontByService[sid] = cur;
      }

      // 4. BYOL addon per service
      for (const sid of svcIds) {
        const sel = selections[sid];
        if (!sel || !Array.isArray(sel.addons)) continue;
        const hasByol = sel.addons.includes('byol');
        const hadByol = !!p.byolByService[sid];
        if (hasByol && !hadByol) {
          push(
            'Bring Your Own List discount applied',
            '15% off the ' + svcName(sid) + ' retainer when you supply a verified prospect list.',
            'We still enrich, copywrite, and run the cadence.'
          );
        }
        p.byolByService[sid] = hasByol;
      }

      // 5. Promo code
      const curCode = state.promoApplied?.code || null;
      const curPct = state.promoApplied?.pct || 0;
      if (curCode && curCode !== p.promoCode) {
        push(
          'Promo code applied',
          curPct + '% off your monthly total with promo ' + curCode + '.',
          'Remove with the X next to the promo chip in your summary.'
        );
      }
      p.promoCode = curCode;

      // 6. Agency multiplier
      const agyMult = window.getAgencyMultiplier ? window.getAgencyMultiplier(state) : 1;
      if (agyMult < 1 && agyMult !== p.agencyMult) {
        const off = Math.round((1 - agyMult) * 100);
        const isWl = state.intentId === 'agency-whitelabel';
        push(
          (isWl ? 'White-label' : 'Agency partner') + ' discount applied',
          off + '% off every service tier, automatically.',
          'Reflected on every line in your summary.'
        );
      }
      p.agencyMult = agyMult;

      // 7. Growing My Agency path selected
      const curIntent = state.intentId || null;
      if (curIntent === 'agency-own' && p.intentId !== 'agency-own') {
        push(
          'Growing My Agency path selected',
          'On this path, we offer Sales & Demand Generation and Talent Solutions. These are the services that work best for agency growth.',
          null
        );
      }
      p.intentId = curIntent;
    }, [
      state?.selections,
      state?.promoApplied,
      state?.intentId,
      state?.clientTypeId,
    ]);

    if (!toasts.length) return null;
    return React.createElement(
      'div',
      { className: 'discount-toast-stack', 'aria-live': 'polite' },
      toasts.map(t =>
        React.createElement(
          'div',
          {
            key: t.id,
            className: 'discount-toast' + (t.leaving ? ' discount-toast--leaving' : ''),
            role: 'status',
          },
          React.createElement(
            'span',
            { className: 'discount-toast__icon', 'aria-hidden': 'true' },
            React.createElement(
              'svg',
              { viewBox: '0 0 24 24', width: 18, height: 18, fill: 'none', stroke: 'currentColor',
                strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round' },
              React.createElement('path', { d: 'M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z' }),
              React.createElement('line', { x1: 7, y1: 7, x2: 7.01, y2: 7 })
            )
          ),
          React.createElement(
            'div',
            { className: 'discount-toast__body' },
            React.createElement('div', { className: 'discount-toast__title' }, t.title),
            React.createElement('div', { className: 'discount-toast__copy' }, t.body),
            t.meta && React.createElement('div', { className: 'discount-toast__meta' }, t.meta)
          ),
          React.createElement(
            'button',
            {
              type: 'button',
              className: 'discount-toast__close',
              onClick: () => dismiss(t.id),
              'aria-label': 'Dismiss',
            },
            React.createElement(
              'svg',
              { viewBox: '0 0 24 24', width: 14, height: 14, fill: 'none', stroke: 'currentColor',
                strokeWidth: 2.4, strokeLinecap: 'round', strokeLinejoin: 'round' },
              React.createElement('line', { x1: 18, y1: 6, x2: 6, y2: 18 }),
              React.createElement('line', { x1: 6, y1: 6, x2: 18, y2: 18 })
            )
          )
        )
      )
    );
  }

  window.DiscountToastManager = DiscountToastManager;
})();
