// pricing.jsx — Halcyon Pilates pricing widget.
// Three sections — New Client Specials, Memberships, Class Packs —
// each laid out as a responsive grid of cards. Card visual language
// follows the Appointment widget: surface-tinted panels, accent-colored
// callout banners, panel-text typography, and the shared radius tweak.

const { useState: usePricingState, useEffect: usePricingEffect } = React;

const PRICING_BREAKPOINT = 760;
function usePricingMobile() {
  const [m, setM] = usePricingState(
    typeof window !== 'undefined' ? window.innerWidth < PRICING_BREAKPOINT : false
  );
  usePricingEffect(() => {
    const onResize = () => setM(window.innerWidth < PRICING_BREAKPOINT);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);
  return m;
}

function fmtMoneyPricing(n) {
  return Number.isInteger(n) ? `$${n}` : `$${n.toFixed(2)}`;
}

// ────────────────────────────────────────────────────────────────
// Data
// ────────────────────────────────────────────────────────────────
const NEW_CLIENT_SPECIALS = [
  {
    id: 'discovery',
    name: 'Discovery Session',
    price: 95,
    cadence: 'one-time',
    description:
      'A one-on-one private session designed to help you explore whether Pilates fits your lifestyle. Perfect for beginners unsure about Pilates.',
  },
  {
    id: 'intro-classes',
    name: 'Intro 3-Pack of Classes',
    price: 99,
    cadence: 'one-time',
    description:
      'Three group classes to use at your convenience. A great way to see if Pilates is right for you. Expires 30 days from purchase.',
  },
  {
    id: 'intro-privates',
    name: 'Intro 3-Pack of Privates',
    price: 300,
    cadence: 'one-time',
    description:
      'Three one-on-one private sessions tailored to your goals. Ideal for those preparing for group classes. Expires 30 days from purchase.',
  },
];

const MEMBERSHIPS = [
  {
    id: 'mem-4',
    name: '4 Classes / month',
    price: 129,
    cadence: 'per month',
    description:
      'Access to four Pilates classes a month. Includes all three studios and exclusive members-only sessions.',
  },
  {
    id: 'mem-8',
    name: '8 Classes / month',
    price: 229,
    cadence: 'per month',
    callout: 'Most popular',
    description:
      'Eight classes a month for the regular practitioner. Includes all studios, members-only sessions, and priority booking.',
  },
  {
    id: 'mem-unlimited',
    name: 'Unlimited Monthly',
    price: 289,
    cadence: 'per month',
    callout: 'Best value',
    description:
      'Take as many classes as you like, up to one per day. Members-only sessions, workshops, and guest passes included.',
  },
];

const CLASS_PACKS = [
  {
    id: 'pack-5-mat',
    name: '5-Pack Mat Classes',
    price: 155,
    cadence: 'one-time',
    description:
      'Five mat class punches, clearly labeled on the schedule. Cards expire six weeks from the date of purchase.',
  },
  {
    id: 'pack-5-equip',
    name: '5-Pack Equipment',
    price: 215,
    cadence: 'one-time',
    description:
      'Five classes across Reformer, Chair, Springboard, Jumpboard and more. Must be used within six weeks of purchase.',
  },
  {
    id: 'pack-10-mat',
    name: '10-Pack Mat Classes',
    price: 295,
    cadence: 'one-time',
    description:
      'Ten mat class punches with extended use. Cards expire three months from the date of purchase.',
  },
  {
    id: 'pack-10-equip',
    name: '10-Pack Equipment',
    price: 395,
    cadence: 'one-time',
    description:
      'Ten classes across all equipment offerings — Reformer, Chair, Springboard, Jumpboard, Open Studio and more. Expires three months from purchase.',
  },
];

// ────────────────────────────────────────────────────────────────
// Root
// ────────────────────────────────────────────────────────────────
function PricingApp({ brandId = 'halcyon' }) {
  const baseBrand = window.BRANDS[brandId];
  const mobile = usePricingMobile();

  const tweaksEnabled = typeof window !== 'undefined' && window.PRICING_TWEAKS_ENABLED;
  const defaults = (typeof window !== 'undefined' && window.PRICING_TWEAK_DEFAULTS) || {};
  const [t, setTweak] = (tweaksEnabled ? window.useTweaks(defaults) : [defaults, () => {}]);

  const brand = tweaksEnabled ? {
    ...baseBrand,
    accent:        t.accent     ?? baseBrand.accent,
    accentDeep:    t.accent     ?? baseBrand.accentDeep,
    accentSoft:    baseBrand.accentSoft,
    surface:       t.panel      ?? baseBrand.surface,
    border:        t.lineColor  ?? baseBrand.border,
    ink:           t.headline   ?? baseBrand.ink,
    inkSoft:       t.details    ?? baseBrand.inkSoft,
    panelInk:      t.panelInk     ?? t.headline ?? baseBrand.ink,
    panelInkSoft:  t.panelInkSoft ?? t.details  ?? baseBrand.inkSoft,
    displayFont:   t.font       ?? baseBrand.displayFont,
    bodyFont:      t.font       ?? baseBrand.bodyFont,
    displayWeight: t.weight     ?? baseBrand.displayWeight,
    _radius:       t.radius,
    _buttonTextColor: t.buttonTextColor,
    _callout:         t.callout       ?? baseBrand.accent,
    _calloutText:     t.calloutText   ?? '#FFFFFF',
  } : {
    ...baseBrand,
    panelInk:     baseBrand.ink,
    panelInkSoft: baseBrand.inkSoft,
  };
  const appBg = tweaksEnabled ? (t.background ?? '#FFFFFF') : '#FFFFFF';

  return (
    <div style={{
      background: appBg, color: brand.ink,
      minHeight: '100vh', fontFamily: brand.bodyFont,
    }}>
      <BrandBar brand={brand} mobile={mobile} />

      <div style={{
        maxWidth: 1180, margin: '0 auto',
        padding: mobile ? '20px 16px 64px' : '32px 32px 80px',
      }}>
        <PricingSection brand={brand} mobile={mobile}
          title="New Client Specials"
          subtitle="Welcome offers for your first visit."
          items={NEW_CLIENT_SPECIALS}
          hideCallouts={!!t.hideCallouts}
          hideDescription={!!t.hideDescription}
          hideButton={!!t.hideButton} />

        <PricingSection brand={brand} mobile={mobile}
          title="Memberships"
          subtitle="Recurring monthly access — cancel anytime."
          items={MEMBERSHIPS}
          hideCallouts={!!t.hideCallouts}
          hideDescription={!!t.hideDescription}
          hideButton={!!t.hideButton} />

        <PricingSection brand={brand} mobile={mobile}
          title="Class Packs"
          subtitle="Punch cards you can use at your own pace."
          items={CLASS_PACKS}
          hideCallouts={!!t.hideCallouts}
          hideDescription={!!t.hideDescription}
          hideButton={!!t.hideButton} />
        <PoweredByZipper />
      </div>

      {tweaksEnabled && <PricingTweaks t={t} setTweak={setTweak} />}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// BrandBar — matches the Appointment widget header.
// ────────────────────────────────────────────────────────────────
function BrandBar({ brand, mobile }) {
  return (
    <div style={{
      borderBottom: `1px solid ${brand.border}`,
      background: '#fff',
      padding: mobile ? '14px 16px' : '18px 32px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      gap: 12,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{
          width: mobile ? 30 : 34, height: mobile ? 30 : 34,
          borderRadius: 8,
          background: brand.accent, color: '#fff',
          display: 'grid', placeItems: 'center',
          fontFamily: brand.displayFont, fontWeight: 800,
          fontSize: mobile ? 13 : 15, letterSpacing: '0.02em',
        }}>H</div>
        <div style={{
          fontFamily: brand.displayFont, fontWeight: brand.displayWeight,
          fontSize: mobile ? 16 : 18, color: brand.ink, letterSpacing: '-0.01em',
        }}>Halcyon Pilates</div>
      </div>
    </div>
  );
}

function SignInButton({ brand }) {
  return (
    <button type="button" style={{
      background: 'transparent', border: 0, padding: '4px 0',
      display: 'inline-flex', alignItems: 'center', gap: 6,
      fontFamily: brand.bodyFont, fontSize: 12, fontWeight: 700,
      letterSpacing: '0.08em', textTransform: 'uppercase', color: brand.accent,
      cursor: 'pointer',
    }}>
      <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
           strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
        <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4" />
        <polyline points="10 17 15 12 10 7" />
        <line x1="15" y1="12" x2="3" y2="12" />
      </svg>
      Sign in
    </button>
  );
}

// ────────────────────────────────────────────────────────────────
// Section + Card
// ────────────────────────────────────────────────────────────────
function PricingSection({ brand, mobile, title, subtitle, items, hideCallouts, hideDescription, hideButton }) {
  const anyCallout = !hideCallouts && items.some(i => !!i.callout);
  return (
    <section style={{ marginTop: mobile ? 22 : 34 }}>
      <div style={{ marginBottom: mobile ? 14 : 18 }}>
        <h2 style={{
          margin: 0,
          fontFamily: brand.displayFont, fontWeight: 700,
          fontSize: mobile ? 19 : 22, letterSpacing: '-0.01em',
          color: brand.ink,
        }}>{title}</h2>
        {subtitle && (
          <div style={{
            marginTop: 4,
            fontFamily: brand.bodyFont, fontSize: 13.5, color: brand.inkSoft,
          }}>{subtitle}</div>
        )}
      </div>

      <div style={{
        display: 'grid',
        gridTemplateColumns: mobile ? '1fr' : 'repeat(3, minmax(0, 1fr))',
        gap: mobile ? 12 : 16,
        alignItems: 'stretch',
      }}>
        {items.map(item => (
          <PricingCard key={item.id} brand={brand} mobile={mobile}
                       item={item}
                       reserveCalloutSpace={anyCallout}
                       hideCallouts={hideCallouts}
                       hideDescription={hideDescription}
                       hideButton={hideButton} />
        ))}
      </div>
    </section>
  );
}

function PricingCard({ brand, mobile, item, reserveCalloutSpace, hideCallouts, hideDescription, hideButton }) {
  const radius = brand._radius != null ? brand._radius : 12;
  const showCallout = !!item.callout && !hideCallouts;
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', height: '100%',
      border: `1px solid ${brand.border}`,
      borderRadius: radius,
      background: brand.surface,
      overflow: 'hidden',
      animation: 'pricing-fadeIn .2s ease',
    }}>
      {reserveCalloutSpace && (
        <div style={{
          background: showCallout ? (brand._callout || brand.accent) : 'transparent',
          color: showCallout ? (brand._calloutText || '#fff') : 'transparent',
          padding: mobile ? '6px 14px' : '8px 18px',
          fontFamily: brand.bodyFont, fontSize: 11, fontWeight: 700,
          letterSpacing: '0.12em', textTransform: 'uppercase',
          minHeight: mobile ? 26 : 32,
        }}>
          {showCallout ? item.callout : '·'}
        </div>
      )}

      <div style={{
        flex: 1,
        padding: mobile ? '16px 16px 18px' : '20px 22px 24px',
        display: 'flex', flexDirection: 'column', gap: mobile ? 10 : 12,
      }}>
        <div style={{
          fontFamily: brand.displayFont, fontWeight: 700,
          fontSize: mobile ? 17 : 19, letterSpacing: '-0.01em',
          color: brand.panelInk,
        }}>{item.name}</div>

        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
          <div style={{
            fontFamily: brand.displayFont, fontWeight: 800,
            fontSize: mobile ? 30 : 36, letterSpacing: '-0.02em',
            color: brand.panelInk, lineHeight: 1,
          }}>{fmtMoneyPricing(item.price)}</div>
          <div style={{
            fontFamily: brand.bodyFont, fontSize: 12.5,
            color: brand.panelInkSoft,
          }}>{item.cadence}</div>
        </div>

        {!hideDescription && (
          <div style={{
            fontFamily: brand.bodyFont, fontSize: 13.5, lineHeight: 1.55,
            color: brand.panelInkSoft, flex: 1,
          }}>{item.description}</div>
        )}
        {hideDescription && <div style={{ flex: 1 }} />}

        {!hideButton && <BuyButton brand={brand} />}
      </div>
    </div>
  );
}

function BuyButton({ brand }) {
  const textColor = brand._buttonTextColor || '#fff';
  return (
    <button
      type="button"
      style={{
        marginTop: 4,
        background: brand.accent, color: textColor,
        border: 0,
        borderRadius: brand._radius != null ? brand._radius : 10,
        padding: '12px 18px',
        fontFamily: brand.displayFont, fontWeight: 700, fontSize: 13.5,
        letterSpacing: '-0.005em', cursor: 'pointer',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
      }}>
      Buy now
      <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
           strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
        <line x1="5" y1="12" x2="19" y2="12" />
        <polyline points="12 5 19 12 12 19" />
      </svg>
    </button>
  );
}

// ────────────────────────────────────────────────────────────────
// Tweaks panel — mirrors the Appointment widget's controls.
// ────────────────────────────────────────────────────────────────
function PricingTweaks({ t, setTweak }) {
  const {
    TweaksPanel: Panel, TweakSection: Section, TweakColor: Color,
    TweakSlider: Slider, TweakSelect: Select, TweakToggle: Toggle,
    TweakButton: Button,
  } = window;
  const resetAll = () => {
    const defaults = (typeof window !== 'undefined' && window.PRICING_TWEAK_DEFAULTS) || {};
    Object.keys(defaults).forEach(k => setTweak(k, defaults[k]));
  };
  usePricingEffect(() => {
    if (!Panel) return;
    const id = window.setTimeout(() => window.postMessage({ type: '__activate_edit_mode' }, '*'), 0);
    return () => window.clearTimeout(id);
  }, [Panel]);
  if (!Panel) return null;
  const FONTS = [
    "'Poppins', system-ui, sans-serif",
    "'Inter', system-ui, sans-serif",
    "'Sora', system-ui, sans-serif",
    "'Open Sans', system-ui, sans-serif",
    "'DM Sans', system-ui, sans-serif",
    "'Manrope', system-ui, sans-serif",
    "'Bebas Neue', sans-serif",
    "'Playfair Display', serif",
  ];
  const fontLabel = (f) => f.replace(/['"]/g, '').split(',')[0];
  return (
    <Panel title="Studio settings" noDeckControls={true}>
      <Section label="Surfaces" />
      <Color label="Accent"      value={t.accent}     onChange={(v) => setTweak('accent', v)} />
      <Color label="Background"  value={t.background} onChange={(v) => setTweak('background', v)} />
      <Color label="Panel"       value={t.panel}      onChange={(v) => setTweak('panel', v)} />
      <Color label="Line color"  value={t.lineColor || '#ECECEC'}
                                 onChange={(v) => setTweak('lineColor', v)} />

      <Section label="Text on background" />
      <Color label="Primary"     value={t.headline}   onChange={(v) => setTweak('headline', v)} />
      <Color label="Secondary"   value={t.details}    onChange={(v) => setTweak('details', v)} />

      <Section label="Text on panel" />
      <Color label="Primary"     value={t.panelInk}     onChange={(v) => setTweak('panelInk', v)} />
      <Color label="Secondary"   value={t.panelInkSoft} onChange={(v) => setTweak('panelInkSoft', v)} />

      <Section label="Text on accent" />
      <Color label="Button text" value={t.buttonTextColor || '#FFFFFF'}
                                 onChange={(v) => setTweak('buttonTextColor', v)} />

      <Section label="Callout" />
      <Color label="Background" value={t.callout}     onChange={(v) => setTweak('callout', v)} />
      <Color label="Text"       value={t.calloutText} onChange={(v) => setTweak('calloutText', v)} />

      <Section label="Typography" />
      <Select label="Font family" value={t.font}
              options={FONTS.map(f => ({ value: f, label: fontLabel(f) }))}
              onChange={(v) => setTweak('font', v)} />
      <Slider label="Headline weight" value={t.weight} min={300} max={800} step={100}
              onChange={(v) => setTweak('weight', v)} />

      <Section label="Shape" />
      <Slider label="Panels &amp; buttons" value={t.radius} min={0} max={28} step={1} unit="px"
              onChange={(v) => setTweak('radius', v)} />

      <Section label="Hide" />
      <Toggle label="Callout banners" value={!!t.hideCallouts}    onChange={(v) => setTweak('hideCallouts', v)} />
      <Toggle label="Description"     value={!!t.hideDescription} onChange={(v) => setTweak('hideDescription', v)} />
      <Toggle label="Button"          value={!!t.hideButton}      onChange={(v) => setTweak('hideButton', v)} />

      <Section label="" />
      <Button label="Restore default settings" secondary onClick={resetAll} />
    </Panel>
  );
}

function PoweredByZipper() {
  return (
    <div style={{
      padding: '36px 0 8px',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      gap: 10,
      fontSize: 10.5, fontWeight: 600, letterSpacing: '0.1em',
      textTransform: 'uppercase', color: '#9CA3AF',
    }}>
      <span>Powered by</span>
      <img src="zipper-logo-grey.svg" alt="Zipper" height="18"
           style={{ display: 'block', height: 18, width: 'auto' }} />
    </div>
  );
}

// Mount
const pricingRoot = ReactDOM.createRoot(document.getElementById('root'));
pricingRoot.render(<PricingApp brandId="halcyon" />);

// Shared fade-in.
const pricingStyleEl = document.createElement('style');
pricingStyleEl.textContent = `@keyframes pricing-fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }`;
document.head.appendChild(pricingStyleEl);
