// Editorial Luxury — shared components
const { useState, useEffect, useRef } = React;

const D = window.EH_DATA;
const API = window.EH_API;

// Logo
const EditorialLogo = ({ light }) => (
  <a href="#/" className="logo" style={light ? {color: '#ffffff'} : {}}>
    <span className="mark"><img src="assets/logo.png" alt="Estetic Hall" /></span>
    <span className="txt"><b>ESTETIC HALL</b><span>бьюти-коворкинг</span></span>
  </a>
);

// Header used on landing only
const EditorialHeader = ({ dark }) => {
  const [scrolled, setScrolled] = useState(false);
  const [user, setUser] = useState(null);
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(() => {
    const f = () => setScrolled(window.scrollY > 60);
    window.addEventListener('scroll', f);
    return () => window.removeEventListener('scroll', f);
  }, []);
  useEffect(() => {
    let active = true;
    API.me().then(r => { if (active) setUser(r.user); }).catch(() => {});
    return () => { active = false; };
  }, []);
  useEffect(() => {
    const f = () => setMenuOpen(false);
    window.addEventListener('hashchange', f);
    return () => window.removeEventListener('hashchange', f);
  }, []);
  const cls = `eh-header ${dark ? 'dark' : ''} ${scrolled ? 'scrolled' : ''} ${menuOpen ? 'menu-open' : ''}`;
  const close = () => setMenuOpen(false);
  return (
    <header className={cls}>
      <div className="container">
        <EditorialLogo />
        <nav className="nav">
          <a href="#book">Аренда и цены</a>
          <a href="#events">Аренда для мероприятий</a>
          <a href="#/reviews">Отзывы</a>
          <a href="#contact">Контакты</a>
        </nav>
        <div className="right">
          {D.brand.phone && <a href={`tel:${D.brand.phone}`} className="header-phone hide-mobile" title="Позвонить">{D.brand.phone}</a>}
          <a href={D.brand.vk || 'https://vk.ru/club238245047'} target="_blank" rel="noopener noreferrer" className="header-social" title="ВКонтакте" aria-label="ВКонтакте">
            <svg width="26" height="16" viewBox="0 0 24 14" fill="#ffffff" aria-hidden="true">
              <path d="M13.162 13.275c-5.475 0-8.6-3.812-8.738-10.137h2.756c.094 4.65 2.13 6.605 3.738 7.012V3.138h2.612v4.038c1.575-.175 3.225-1.987 3.788-4.038h2.6c-.425 2.525-2.225 4.337-3.5 5.082 1.275.602 3.325 2.187 4.112 5.055h-2.862c-.613-1.925-2.113-3.413-4.138-3.62v3.62h-.368z"/>
            </svg>
          </a>
          <a href={D.brand.instagram || 'https://instagram.com/'} target="_blank" rel="noopener noreferrer" className="header-social" title="Instagram" aria-label="Instagram">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ffffff" strokeWidth="2" aria-hidden="true">
              <rect x="2.5" y="2.5" width="19" height="19" rx="5.5"/>
              <circle cx="12" cy="12" r="4.4"/>
              <circle cx="17.6" cy="6.4" r="1.3" fill="#ffffff" stroke="none"/>
            </svg>
          </a>
          <a href={D.brand.maxGroup || 'https://max.ru/'} target="_blank" rel="noopener noreferrer" className="header-social header-social--max" title="Группа в MAX" aria-label="Группа в MAX">MAX</a>
          {user ? (
            <a href={user.role === 'admin' ? '#/admin' : '#/cabinet'} className="header-avatar" title={user.name} aria-label={`Кабинет — ${user.name}`}>{user.name.trim().charAt(0)}</a>
          ) : (
            <a href="#/login" className="btn btn--outline hide-mobile" style={{padding: '10px 20px', fontSize: 11}}>Войти</a>
          )}
          <a href="#book" className="btn btn--gold hide-mobile" style={{padding: '12px 22px', fontSize: 11}}>Онлайн запись</a>
          <button className={`burger ${menuOpen ? 'open' : ''}`} onClick={() => setMenuOpen(o => !o)} aria-label="Меню" aria-expanded={menuOpen}>
            <span></span><span></span><span></span>
          </button>
        </div>
      </div>
      {menuOpen && (
        <div className="mobile-menu">
          <a href="#book" onClick={close}>Аренда и цены</a>
          <a href="#events" onClick={close}>Аренда для мероприятий</a>
          <a href="#gallery" onClick={close}>Галерея</a>
          <a href="#/reviews" onClick={close}>Отзывы</a>
          <a href="#contact" onClick={close}>Контакты</a>
          {D.brand.phone && <a href={`tel:${D.brand.phone}`} onClick={close}>{D.brand.phone}</a>}
          {user
            ? <a href={user.role === 'admin' ? '#/admin' : '#/cabinet'} onClick={close} className="mm-accent">Личный кабинет</a>
            : <a href="#/login" onClick={close} className="mm-accent">Войти</a>}
          <a href="#book" onClick={close} className="mm-cta">Онлайн запись →</a>
        </div>
      )}
    </header>
  );
};

// Footer
const EditorialFooter = () => (
  <footer className="eh-footer">
    <div className="container">
      <div className="eh-footer-grid">
        {/* 1. Рабочие места */}
        <div className="ef-col">
          <h5>Рабочие места</h5>
          <ul>
            <li><a href="#book">Аренда места парикмахера</a></li>
            <li><a href="#book">Аренда кресла барбера</a></li>
            <li><a href="#book">Аренда столика маникюра</a></li>
            <li><a href="#book">Аренда места педикюра</a></li>
            <li><a href="#book">Аренда места визажиста / бровиста</a></li>
          </ul>
        </div>

        {/* 2. Отдельные кабинеты */}
        <div className="ef-col">
          <h5>Отдельные кабинеты</h5>
          <ul>
            <li><a href="#book">Кабинет с кушеткой</a></li>
            <li><a href="#book">Кабинет косметолога</a></li>
            <li><a href="#book">Кабинет с автозагаром</a></li>
            <li><a href="#book">Кабинеты свободного назначения</a></li>
          </ul>
        </div>

        {/* 3. О бьюти-коворкинге */}
        <div className="ef-col">
          <h5>О бьюти-коворкинге</h5>
          <ul>
            <li><a href="#book">Аренда и цены</a></li>
            <li><a href="#events">Аренда зала для мероприятий</a></li>
            <li><a href="#gallery">Галерея</a></li>
            <li><a href="#/reviews">Отзывы</a></li>
            <li><a href="#contact">Контакты</a></li>
            <li><a href={D.brand.vk || 'https://vk.ru/club238245047'} target="_blank" rel="noopener noreferrer">ВКонтакте</a></li>
            <li><a href={D.brand.instagram || 'https://instagram.com/'} target="_blank" rel="noopener noreferrer">Instagram</a></li>
            <li><a href={D.brand.maxGroup || 'https://max.ru/'} target="_blank" rel="noopener noreferrer">Группа в MAX</a></li>
          </ul>
        </div>

        {/* 4. Забронировать — крупный CTA-блок */}
        <div className="ef-col ef-col--cta">
          <h5>Забронировать</h5>
          {D.brand.phone && (
            <a href={`tel:${D.brand.phone}`} className="ef-phone">{D.brand.phone}</a>
          )}
          <ul className="ef-actions">
            <li><a href="#book">Забронировать онлайн →</a></li>
            <li><a href={D.brand.vk || 'https://vk.ru/club238245047'} target="_blank" rel="noopener noreferrer">Написать в ВКонтакте →</a></li>
          </ul>
          <div className="ef-meta">
            <div style={{whiteSpace: 'pre-line'}}>{D.brand.address}</div>
            <div className="ef-hours">{D.brand.hours}</div>
          </div>
        </div>
      </div>
      <div className="eh-footer-bottom">
        <span>© 2026 Бьюти-коворкинг Estetic Hall · {(D.brand.address || '').replace(/\s*\n\s*/g, ' ')}</span>
        <span className="lks">
          <a href="#/privacy">Политика конфиденциальности</a>
          <a href="#/offer">Оферта</a>
        </span>
      </div>
    </div>
  </footer>
);

// Auth photo column (shared for login + register)
const AuthPhoto = ({ quote, by, bg }) => (
  <div className="auth-photo" style={{backgroundImage: `url(${bg || D.photos.heroInterior})`}}>
    <div className="auth-overlay">
      <a href="#/" className="logo" style={{color: '#ffffff'}}>
        <span className="mark"><img src="assets/logo.png" alt="Estetic Hall" /></span>
        <span className="txt"><b>ESTETIC HALL</b><span>бьюти-коворкинг</span></span>
      </a>
      <div>
        <div className="quote">«{quote}»</div>
        <div className="quote-by">— {by}</div>
      </div>
    </div>
  </div>
);

// Room detail drawer (used by landing) — real schedule from API
const isoLocal = (d) => `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
const DOW = ['ВС','ПН','ВТ','СР','ЧТ','ПТ','СБ'];
const MON = ['янв','фев','мар','апр','мая','июн','июл','авг','сен','окт','ноя','дек'];

// Зоны, на которые можно тратить часы абонемента (синхронно с бэкендом eh_abonement_zones)
const EH_ABONEMENT_ZONES = ['hair', 'nails', 'makeup', 'pedicure', 'barber'];

// «5 июл» из ISO-даты
const fmtRuD = (iso) => {
  const p = String(iso || '').split('-');
  if (p.length !== 3) return iso;
  return `${parseInt(p[2], 10)} ${MON[parseInt(p[1], 10) - 1]}`;
};

const RoomDrawer = ({ room, onClose, onBook }) => {
  const [photoIdx, setPhotoIdx] = useState(0);
  const [mode, setMode] = useState('hour');   // 'hour' — по часам | 'day' — весь день | 'month' — 30 дней
  const [selectedDay, setSelectedDay] = useState(0);
  const [selectedSlots, setSelectedSlots] = useState([]);
  const [busy, setBusy] = useState([]);
  const [loadingSlots, setLoadingSlots] = useState(true);
  const [quote, setQuote] = useState(null); // { price, originalPrice, discountPct, discountLabel }
  const [sub, setSub] = useState({ hours: 0, days: 0 }); // остатки абонементов (часы и дни)
  const [useAbonement, setUseAbonement] = useState(false);
  const [longDate, setLongDate] = useState(isoLocal(new Date())); // дата для режимов «день»/«месяц»
  const [longBusy, setLongBusy] = useState(null); // null = проверяем; { busy: [], busyDates: [] }

  const today = new Date(); today.setHours(0,0,0,0);
  const days = Array.from({length: 7}, (_, i) => { const d = new Date(today); d.setDate(today.getDate() + i); return d; });
  const openH = parseInt(String(D.brand.open || '09:00').slice(0, 2), 10);
  const closeH = parseInt(String(D.brand.close || '21:00').slice(0, 2), 10);
  const hours = Array.from({length: Math.max(0, closeH - openH)}, (_, i) => openH + i);
  const photos = room ? room.photos.map(ehPhoto) : [];
  const maxLongDate = isoLocal(new Date(Date.now() + 90 * 24 * 60 * 60 * 1000)); // бронь до +90 дней

  // Подтягиваем остатки абонементов (тихо; если не авторизован — нули)
  useEffect(() => {
    if (!room) return;
    let active = true;
    setUseAbonement(false);
    API.mySubscription()
      .then(r => { if (active) setSub({
        hours: (r.balanceHours != null ? r.balanceHours : r.balance) || 0,
        days: r.balanceDays || 0,
      }); })
      .catch(() => { if (active) setSub({ hours: 0, days: 0 }); });
    return () => { active = false; };
  }, [room && room.id]);

  // Load real availability for the selected day
  useEffect(() => {
    if (!room) return;
    let active = true;
    setSelectedSlots([]);
    setLoadingSlots(true);
    API.availability(room.id, isoLocal(days[selectedDay]))
      .then(r => { if (active) setBusy(r.busy || []); })
      .catch(() => { if (active) setBusy([]); })
      .then(() => { if (active) setLoadingSlots(false); });
    return () => { active = false; };
  }, [room && room.id, selectedDay]);

  // Занятость для режимов «день» (1 дата) и «месяц» (30 дат подряд)
  useEffect(() => {
    if (!room || mode === 'hour') return;
    let active = true;
    setLongBusy(null);
    API.availability(room.id, longDate, mode === 'month' ? 30 : 1)
      .then(r => { if (active) setLongBusy({ busy: r.busy || [], busyDates: r.busyDates || [] }); })
      .catch(() => { if (active) setLongBusy({ busy: [], busyDates: [] }); });
    return () => { active = false; };
  }, [room && room.id, mode, longDate]);

  // При смене режима сбрасываем расчёты
  useEffect(() => { setUseAbonement(false); setQuote(null); }, [mode]);

  // Каждый раз когда меняется выбор (часы или режим/дата) — запрашиваем у сервера итог со скидкой
  useEffect(() => {
    if (!room) return;
    if (mode === 'hour' && !selectedSlots.length) { setQuote(null); return; }
    let active = true;
    const t = setTimeout(() => {
      const body = mode === 'hour'
        ? { roomId: room.id, slots: selectedSlots }
        : { roomId: room.id, kind: mode };
      API.quote(body)
        .then(q => { if (active) setQuote(q); })
        .catch(() => { if (active) setQuote(null); });
    }, 150);
    return () => { active = false; clearTimeout(t); };
  }, [room && room.id, selectedSlots, mode]);

  if (!room) return null;

  const next = () => setPhotoIdx(i => (i + 1) % photos.length);
  const prev = () => setPhotoIdx(i => (i - 1 + photos.length) % photos.length);

  const now = new Date();
  const isToday = isoLocal(days[selectedDay]) === isoLocal(now);
  const disabled = (h) => busy.includes(h) || (isToday && h <= now.getHours());

  const toggleSlot = (h) => {
    if (disabled(h)) return;
    setSelectedSlots(s => s.includes(h) ? s.filter(x => x !== h) : [...s, h].sort((a,b) => a-b));
  };

  const total = quote ? quote.price
    : (mode === 'hour' ? selectedSlots.length * room.prices.hour
      : mode === 'day' ? room.prices.day : room.prices.month);
  const originalTotal = quote ? quote.originalPrice : total;
  const hasDiscount = quote && quote.discountPct > 0;
  const sel = days[selectedDay];
  const dateLabel = `${sel.getDate()} ${MON[sel.getMonth()]}`;
  // Статус доступности в режимах «день»/«месяц»
  const dayFree = longBusy !== null && longBusy.busy.length === 0;
  const monthFree = longBusy !== null && longBusy.busyDates.length === 0;
  const monthEnd = isoLocal(new Date(new Date(longDate + 'T00:00:00').getTime() + 29 * 24 * 60 * 60 * 1000));
  const st = room.status === 'free' ? {c:'var(--green)', t:'Свободен сегодня'}
           : room.status === 'partial' ? {c:'#d9a23c', t:'Частично занят'}
           : {c:'var(--red)', t:'Занят сегодня'};

  return (
    <>
      <div className="drawer-overlay" onClick={onClose}></div>
      <aside className="room-detail" role="dialog" aria-label={room.name}>
        <div className="gallery">
          {photos.map((p, i) => (
            <img key={i} src={p} className={i === photoIdx ? 'active' : ''} alt="" />
          ))}
          <div className="gallery-grad"></div>
          <button className="close" onClick={onClose} aria-label="Закрыть">✕</button>
          <div className="gallery-cap"><span className="g-num">{room.num}</span><span className="g-zone">{room.zoneRu}</span></div>
          <div className="arrows">
            <button onClick={prev} aria-label="Предыдущее фото">‹</button>
            <button onClick={next} aria-label="Следующее фото">›</button>
          </div>
          <div className="dots">
            {photos.map((_, i) => (
              <span key={i} className={i === photoIdx ? 'active' : ''} onClick={() => setPhotoIdx(i)}></span>
            ))}
          </div>
        </div>
        <div className="body">
          <div className="rd-head">
            <h3>{room.name}</h3>
            <span className="rd-pill"><i style={{background: st.c}}></i>{st.t}</span>
          </div>
          <div className="meta-row">
            <span className="zone">{room.zoneRu}</span>
            <span className="area">· {room.area} м²</span>
            <span className="from">от <b>{room.prices.hour}₽</b> / час</span>
          </div>

          <p className="desc">{room.desc}</p>

          <h4>Тарифы</h4>
          <div className="prices">
            <div><span>1 час</span><b>{room.prices.hour}₽</b></div>
            <div><span>День</span><b>{room.prices.day}₽</b></div>
            <div><span>Месяц</span><b>{room.prices.month.toLocaleString()}₽</b></div>
          </div>

          <h4>Бронирование · выберите формат</h4>
          <div className="rd-modes" role="tablist">
            <button type="button" className={mode === 'hour' ? 'active' : ''} onClick={() => setMode('hour')}>По часам</button>
            <button type="button" className={mode === 'day' ? 'active' : ''} onClick={() => setMode('day')}>На день</button>
            <button type="button" className={mode === 'month' ? 'active' : ''} onClick={() => setMode('month')}>На месяц</button>
          </div>

          {mode === 'hour' ? (
          <div className="calendar">
            <div className="cal-days">
              {days.map((d, i) => (
                <div key={i} className={`cal-day ${i === selectedDay ? 'active' : ''}`} onClick={() => setSelectedDay(i)}>
                  <span className="dow">{i === 0 ? 'СЕГ' : DOW[d.getDay()]}</span>
                  <span>{d.getDate()}</span>
                </div>
              ))}
            </div>
            {loadingSlots ? (
              <div className="cal-loading">Загрузка расписания…</div>
            ) : (
              <div className="cal-slots">
                {hours.map(h => (
                  <div
                    key={h}
                    className={`cal-slot ${disabled(h) ? 'busy' : ''} ${selectedSlots.includes(h) ? 'selected' : ''}`}
                    onClick={() => toggleSlot(h)}
                  >
                    {String(h).padStart(2, '0')}:00
                  </div>
                ))}
              </div>
            )}
            <div className="cal-legend">
              <span><i className="lg-free"></i>свободно</span>
              <span><i className="lg-busy"></i>занято</span>
              <span><i className="lg-sel"></i>выбрано</span>
            </div>
          </div>
          ) : (
          <div className="rd-long">
            <div className="rd-long-note">
              {mode === 'day'
                ? `Место будет вашим на весь рабочий день (${String(openH).padStart(2, '0')}:00–${String(closeH).padStart(2, '0')}:00).`
                : 'Место закрепляется за вами на 30 дней подряд, начиная с выбранной даты.'}
            </div>
            <div className="rd-long-date">
              <label>{mode === 'day' ? 'Дата' : 'Дата начала'}</label>
              <input type="date" value={longDate} min={isoLocal(new Date())} max={maxLongDate}
                onChange={e => { if (e.target.value) setLongDate(e.target.value); }} />
            </div>
            {longBusy === null ? (
              <div className="cal-loading">Проверяем занятость…</div>
            ) : mode === 'day' ? (
              dayFree
                ? <div className="rd-long-status ok">✓ {fmtRuD(longDate)} — день свободен</div>
                : <div className="rd-long-status no">На {fmtRuD(longDate)} уже есть брони — выберите другую дату</div>
            ) : (
              monthFree
                ? <div className="rd-long-status ok">✓ Свободно · {fmtRuD(longDate)} — {fmtRuD(monthEnd)}</div>
                : <div className="rd-long-status no">Заняты дни: {longBusy.busyDates.slice(0, 4).map(fmtRuD).join(', ')}{longBusy.busyDates.length > 4 ? '…' : ''} — выберите другую дату начала</div>
            )}
          </div>
          )}

          <h4>Что включено</h4>
          <div className="equip">
            {room.equipment.map((e, i) => <div key={i}>{e}</div>)}
          </div>

          <h4>Контакты</h4>
          <div className="rd-contacts">
            <a href={`tel:${D.brand.phone}`}>📞 {D.brand.phone}</a>
            <a href={D.brand.vk || 'https://vk.ru/club238245047'} target="_blank" rel="noopener noreferrer">💬 ВКонтакте</a>
          </div>
        </div>

        {(() => {
          const slotsCount = selectedSlots.length;
          const isHour = mode === 'hour';
          const isDay = mode === 'day';
          // Можно ли бронировать при текущем выборе
          const canBook = isHour ? slotsCount > 0 : (isDay ? dayFree : monthFree);
          // Абонемент: часовой оплачивает часы, дневной — брони на день; месяц — только деньгами
          const abBalance = isHour ? sub.hours : sub.days;
          const abUnit = isHour ? 'ч' : 'дн.';
          const abNeed = isHour ? slotsCount : 1;
          const abonementEligible = mode !== 'month' && EH_ABONEMENT_ZONES.includes(room.zone) && abBalance > 0;
          const enoughUnits = abBalance >= abNeed;
          const payingAbonement = useAbonement && abonementEligible && enoughUnits && canBook;
          const dateISO = isHour ? isoLocal(sel) : longDate;
          const dLabel = isHour ? dateLabel : fmtRuD(longDate);
          const infoLabel = isHour
            ? (slotsCount ? `${slotsCount} ч · ${dateLabel}` : 'Выберите часы')
            : isDay
              ? (canBook ? `Весь день · ${dLabel}` : 'Выберите свободный день')
              : (canBook ? `30 дней · с ${dLabel}` : 'Выберите свободную дату');
          const show = isHour ? slotsCount > 0 : true;
          return (
            <div className={`rd-bar ${show ? 'show' : ''}`}>
              {abonementEligible && (
                <label className={`rd-bar-abonement ${!enoughUnits && canBook ? 'disabled' : ''}`}>
                  <input type="checkbox" checked={payingAbonement}
                    disabled={!canBook || !enoughUnits}
                    onChange={e => setUseAbonement(e.target.checked)} />
                  <span>Оплатить абонементом · осталось {abBalance} {abUnit}
                    {canBook && !enoughUnits && <em> (не хватает {isHour ? 'часов' : 'дней'})</em>}</span>
                </label>
              )}
              <div className="rd-bar-info">
                <span>{infoLabel}</span>
                {payingAbonement ? (
                  <b>Абонемент · {isHour ? `${slotsCount} ч` : '1 день'}</b>
                ) : hasDiscount ? (
                  <div className="rd-bar-price">
                    <span className="rd-bar-old">{originalTotal.toLocaleString()} ₽</span>
                    <b>{total.toLocaleString()} ₽</b>
                  </div>
                ) : (
                  <b>{total.toLocaleString()} ₽</b>
                )}
              </div>
              {!payingAbonement && hasDiscount && (
                <div className="rd-bar-discount">✓ {quote.discountLabel}</div>
              )}
              <button className="btn btn--gold" disabled={!canBook}
                onClick={() => onBook({ room, kind: mode, dateISO, dateLabel: dLabel, slots: selectedSlots, total, payWith: payingAbonement ? 'abonement' : 'money' })}>
                Забронировать →
              </button>
            </div>
          );
        })()}
      </aside>
    </>
  );
};

// Reveal-on-scroll wrapper
const Reveal = ({ children, delay = 0, as: As = 'div', ...rest }) => {
  const ref = useRef(null);
  const [vis, setVis] = useState(false);
  useEffect(() => {
    const o = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setVis(true); o.disconnect(); }
    }, { threshold: 0.12 });
    if (ref.current) o.observe(ref.current);
    return () => o.disconnect();
  }, []);
  return <As ref={ref} className={`reveal ${vis ? 'in' : ''}`} style={{transitionDelay: `${delay}ms`}} {...rest}>{children}</As>;
};

// ============================================
// ОПЛАТА ПЕРЕВОДОМ ПО QR (без эквайринга)
// ============================================

// Платёжная строка по ГОСТ Р 56042-2014 (формат ST00012, кодировка UTF-8).
// Такой QR сканируется в приложениях Сбербанка и большинства банков РФ —
// реквизиты, сумма и назначение подставляются автоматически.
function ehPaymentQRPayload(req, amount, purpose) {
  const parts = [
    'ST00012',
    'Name=' + (req.name || ''),
    'PersonalAcc=' + (req.account || ''),
    'BankName=' + (req.bank || ''),
    'BIC=' + (req.bic || ''),
    'CorrespAcc=' + (req.corr || ''),
  ];
  if (req.inn) parts.push('PayeeINN=' + req.inn);
  if (amount > 0) parts.push('Sum=' + Math.round(amount * 100)); // сумма в копейках
  if (purpose) parts.push('Purpose=' + purpose);
  return parts.join('|');
}

// SVG-разметка QR-кода (пусто, если библиотека не загрузилась — покажем только реквизиты)
function ehPaymentQRSvg(req, amount, purpose) {
  try {
    if (typeof qrcode === 'undefined') return '';
    if (qrcode.stringToBytesFuncs && qrcode.stringToBytesFuncs['UTF-8']) {
      qrcode.stringToBytes = qrcode.stringToBytesFuncs['UTF-8'];
    }
    const qr = qrcode(0, 'M');
    qr.addData(ehPaymentQRPayload(req, amount, purpose), 'Byte');
    qr.make();
    return qr.createSvgTag({ cellSize: 4, margin: 0, scalable: true });
  } catch (e) {
    return '';
  }
}

// Модалка «Оплатите переводом»: QR + реквизиты + пояснение про подтверждение админом.
// payment: { amount, purpose, requisites } (requisites может не быть — возьмём из настроек)
const PaymentModal = ({ payment, onClose, ctaHref, ctaLabel }) => {
  const [copied, setCopied] = useState(null);
  const p = payment || {};
  const req = p.requisites && p.requisites.account ? p.requisites : (D.pay || {});
  const amount = p.amount || 0;
  const purpose = p.purpose || '';
  const svg = React.useMemo(() => ehPaymentQRSvg(req, amount, purpose), [req.account, amount, purpose]);
  if (!payment) return null;

  const copy = async (label, value) => {
    try { await navigator.clipboard.writeText(String(value)); } catch (e) {
      try {
        const ta = document.createElement('textarea');
        ta.value = String(value); document.body.appendChild(ta);
        ta.select(); document.execCommand('copy'); document.body.removeChild(ta);
      } catch (e2) { /* не вышло — покажем без галочки */ }
    }
    setCopied(label);
    setTimeout(() => setCopied(c => (c === label ? null : c)), 2000);
  };

  const Row = ({ label, value, mono }) => (
    <div className="pm-row">
      <span className="pm-row-label">{label}</span>
      <b className={mono ? 'pm-mono' : ''}>{value}</b>
      <button type="button" className="pm-copy" onClick={() => copy(label, value)} title="Скопировать">
        {copied === label ? '✓' : '⧉'}
      </button>
    </div>
  );

  return (
    <>
      <div className="drawer-overlay" style={{zIndex: 130}} onClick={onClose}></div>
      <div className="payment-modal" role="dialog" aria-label="Оплата переводом">
        <button className="ep-close" onClick={onClose} aria-label="Закрыть">×</button>
        <div className="pm-head">
          <span className="kicker">Оплата переводом по QR</span>
          <div className="pm-amount">{amount.toLocaleString('ru-RU')} <span>₽</span></div>
          <div className="pm-purpose">{purpose}</div>
        </div>

        <div className="pm-grid">
          {svg ? (
            <div className="pm-qr">
              <div className="pm-qr-img" dangerouslySetInnerHTML={{ __html: svg }} />
              <span className="pm-qr-hint">Откройте приложение банка → «Оплата по QR» и отсканируйте код. Сумма и реквизиты подставятся сами.</span>
            </div>
          ) : (
            <div className="pm-qr pm-qr--none"><span className="pm-qr-hint">Переведите по реквизитам справа — сумма и назначение указаны выше.</span></div>
          )}
          <div className="pm-req">
            <Row label="Получатель" value={req.name || '—'} />
            {req.inn ? <Row label="ИНН" value={req.inn} mono /> : null}
            <Row label="Счёт" value={req.account || '—'} mono />
            <Row label="Банк" value={req.bank || '—'} />
            <Row label="БИК" value={req.bic || '—'} mono />
            {req.corr ? <Row label="Корсчёт" value={req.corr} mono /> : null}
            <Row label="Сумма" value={amount.toLocaleString('ru-RU') + ' ₽'} />
            <Row label="Назначение" value={purpose} />
          </div>
        </div>

        <div className="pm-note">
          <b>Что дальше?</b> После перевода администратор проверит поступление и подтвердит оплату —
          до этого момента статус будет «Ожидается подтверждение оплаты». Обычно проверка занимает
          немного времени в рабочие часы; место уже удержано за вами.
        </div>

        <div className="pm-actions">
          <a href={ctaHref || '#/cabinet'} className="btn btn--gold" onClick={onClose}>{ctaLabel || 'Я перевёл(а) — в кабинет →'}</a>
          <button type="button" className="btn btn--outline" onClick={onClose}>Закрыть</button>
        </div>
      </div>
    </>
  );
};

// Плавающая кнопка «Написать в MAX» — правый нижний угол, круглая, без подписи
const MaxFab = () => {
  const url = (D.brand && D.brand.maxDm) || 'https://max.ru/+79204770302';
  return (
    <a className="eh-fab eh-fab--max" href={url} target="_blank" rel="noopener noreferrer"
       aria-label="Написать в MAX" title="Написать в MAX">
      <svg viewBox="0 0 48 48" width="32" height="32" aria-hidden="true">
        <path fill="#ffffff" d="M24 9C15.2 9 8 14.9 8 22.2c0 4.1 2.3 7.8 5.9 10.2-.2 1.9-1 3.8-2.2 5.3-.3.4 0 .9.5.8 2.6-.4 5-1.4 7.1-2.9 1.5.4 3.1.7 4.7.7 8.8 0 16-5.9 16-13.2S32.8 9 24 9z"/>
        <text x="24" y="26" textAnchor="middle" fontFamily="Inter, sans-serif" fontSize="10" fontWeight="700" fill="#0a4fb0" letterSpacing="0.3">MAX</text>
      </svg>
    </a>
  );
};

// Expose globally
Object.assign(window, { EditorialLogo, EditorialHeader, EditorialFooter, AuthPhoto, RoomDrawer, Reveal, MaxFab, PaymentModal, ehPaymentQRPayload });
