// Shared React components: Header, Footer, Breadcrumbs, Badges, Icons
const { useState, useEffect, useRef, useMemo, Fragment } = React;

// Случайный класс цвета из палитры employees (a0…a6). Фиксируется на сессию,
// чтобы при переходе между страницами аватар не «мигал» разными цветами.
function getMeAvatarClass() {
  try {
    const key = 'pe-me-avatar-idx';
    let idx = sessionStorage.getItem(key);
    if (idx === null) {
      idx = String(Math.floor(Math.random() * 7));
      sessionStorage.setItem(key, idx);
    }
    return 'a' + idx;
  } catch (e) {
    return 'a' + Math.floor(Math.random() * 7);
  }
}

// ===== ICONS =====
const Icon = {
  Search: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>,
  Menu: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/></svg>,
  Heart: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.29 1.51 4.04 3 5.5l7 7Z"/></svg>,
  HeartFill: (p) => <svg {...p} viewBox="0 0 24 24" fill="currentColor"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.29 1.51 4.04 3 5.5l7 7Z"/></svg>,
  BarChart: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></svg>,
  Cart: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.7 13.4a2 2 0 0 0 2 1.6h9.7a2 2 0 0 0 2-1.6L23 6H6"/></svg>,
  Bell: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>,
  Copy: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>,
  Minus: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>,
  Plus: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>,
  Star: (p) => <svg {...p} viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>,
  ChevronDown: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>,
  ChevronLeft: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6"/></svg>,
  ChevronRight: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>,
  Close: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>,
  Grid: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>,
  List: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>,
  Table: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="16" rx="1"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="10" y1="4" x2="10" y2="20"/></svg>,
  Share: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>,
  Truck: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="1" y="3" width="15" height="13"/><polygon points="16 8 20 8 23 11 23 16 16 16 16 8"/><circle cx="5.5" cy="18.5" r="2.5"/><circle cx="18.5" cy="18.5" r="2.5"/></svg>,
  Card: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="1" y="4" width="22" height="16" rx="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg>,
  Shield: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>,
  Box: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>,
  Info: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>,
  Check: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>,
  Phone: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.33 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/></svg>,
  Mail: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>,
  Clock: (p) => <svg {...p} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>,
};

// ===== LOGO (real Figma SVG) =====
function Logo() {
  return (
    <a href="catalog.html" aria-label="Печной Эксперт" style={{display:'inline-flex',textDecoration:'none'}}>
      <img src="assets/logo-dark.svg" width="130" height="76" alt="Печной Эксперт" style={{display:'block'}}/>
    </a>
  );
}

// ===== useIsMobile hook =====
// Реактивно отслеживает viewport ≤ 767 px. Используется в Header / Footer,
// чтобы автоматически делегировать рендер на window.MobileHeader /
// window.MobileFooter, если они зарегистрированы (mobile.jsx подключён).
function useIsMobile() {
  const [m, setM] = React.useState(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return false;
    return window.matchMedia('(max-width: 767px)').matches;
  });
  React.useEffect(() => {
    if (!window.matchMedia) return;
    const mq = window.matchMedia('(max-width: 767px)');
    const handler = (e) => setM(e.matches);
    if (mq.addEventListener) mq.addEventListener('change', handler);
    else if (mq.addListener) mq.addListener(handler);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', handler);
      else if (mq.removeListener) mq.removeListener(handler);
    };
  }, []);
  return m;
}

// ===== HEADER (auto-responsive wrapper) =====
function Header(props) {
  const isMobile = useIsMobile();
  if (isMobile && window.MobileHeader) {
    return React.createElement(window.MobileHeader, props);
  }
  return React.createElement(HeaderDesktop, props);
}

function HeaderDesktop({ cartCount = 3, favCount = 7, compareCount = 2 }) {
  const [compact, setCompact] = React.useState(false);
  const [query, setQuery] = React.useState('');
  const searchInputRef = React.useRef(null);
  const compactRef = React.useRef(false);
  const tickingRef = React.useRef(false);
  React.useEffect(() => {
    // Hysteresis thresholds: enter compact at 80px, exit at 40px.
    // The gap prevents flicker when header shrink reduces page height
    // and bounces scrollY back across a single threshold.
    const ENTER = 80;
    const EXIT = 40;
    const update = () => {
      tickingRef.current = false;
      const y = window.scrollY;
      const now = compactRef.current;
      let next = now;
      if (!now && y > ENTER) next = true;
      else if (now && y < EXIT) next = false;
      if (next !== now) {
        compactRef.current = next;
        setCompact(next);
      }
    };
    const onScroll = () => {
      if (tickingRef.current) return;
      tickingRef.current = true;
      window.requestAnimationFrame(update);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    update();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <header className="site-header">
      <div className="top-strip">
        <span className="city">Екатеринбург</span>
        <nav>
          <a>Стать партнёром</a>
          <a>Заказать звонок</a>
          <a className="phone">+7 (343) 385-89-50</a>
        </nav>
      </div>
      <div className={`header-main ${compact ? 'compact' : ''}`}>
        <Logo/>
        <button className="catalog-btn">
          Каталог
          <svg className="catalog-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
            <circle cx="5" cy="5" r="1.75" fill="currentColor"/>
            <circle cx="11" cy="5" r="1.75" fill="currentColor"/>
            <circle cx="5" cy="11" r="1.75" fill="currentColor"/>
            <circle cx="11" cy="11" r="1.75" fill="currentColor"/>
          </svg>
        </button>
        <div className="search">
          <input
            ref={searchInputRef}
            value={query}
            onChange={(e)=>setQuery(e.target.value)}
            placeholder="Поиск товара по названию или артикулу"
          />
          {query && (
            <button
              type="button"
              className="search-clear"
              aria-label="Очистить поле"
              onClick={()=>{ setQuery(''); searchInputRef.current?.focus(); }}
            >
              <svg width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
                <path d="M1.5 1.5 L8.5 8.5 M8.5 1.5 L1.5 8.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
              </svg>
            </button>
          )}
          <button className="search-btn"><Icon.Search style={{width:18,height:18}}/></button>
        </div>
        <div className="user-nav">
          <button className="nav-item">
            {favCount > 0 && <span className="badge">{favCount}</span>}
            <Icon.Heart style={{width:26,height:26}}/>
            <span className="nav-label">Избранное</span>
          </button>
          <button className="nav-item">
            {compareCount > 0 && <span className="badge">{compareCount}</span>}
            <Icon.BarChart style={{width:26,height:26}}/>
            <span className="nav-label">Сравнение</span>
          </button>
          <button className="nav-item">
            {cartCount > 0 && <span className="badge">{cartCount}</span>}
            <Icon.Cart style={{width:26,height:26}}/>
            <span className="nav-label">Корзина</span>
          </button>
          <button className="profile-btn" aria-label="Личный кабинет, 153 уведомления">
            <span className="avatar-ring">
              <span className={'avatar-initials ' + getMeAvatarClass()} aria-hidden="true">ВЗ</span>
            </span>
            <span className="notif-badge">153</span>
          </button>
        </div>
      </div>
    </header>
  );
}

// ===== BREADCRUMBS =====
function Breadcrumbs({ items }) {
  return (
    <div className="breadcrumbs">
      {items.map((it, i) => (
        <span key={i} className="bc-item" style={{display:'inline-flex',alignItems:'center',gap:8}}>
          {i > 0 && <span className="sep">/</span>}
          {it.href ? <a href={it.href}>{it.label}</a> : <span className="current">{it.label}</span>}
        </span>
      ))}
    </div>
  );
}

// ===== FOOTER (auto-responsive wrapper) =====
function Footer(props) {
  const isMobile = useIsMobile();
  if (isMobile && window.MobileFooter) {
    return React.createElement(window.MobileFooter, props);
  }
  return React.createElement(FooterDesktop, props);
}

function FooterDesktop() {
  return (
    <footer className="site-footer">
      <div className="cols">
        <div>
          <h4>Компания</h4>
          <a>Контакты</a>
          <a>Вакансии</a>
          <a>Антикоррупция</a>
          <a>Реквизиты</a>
        </div>
        <div>
          <h4>Партнёру</h4>
          <a href="payment.html">Условия оплаты</a>
          <a href="delivery.html">Условия доставки</a>
          <a>Гарантия</a>
          <a>Противодействие коррупции</a>
          <a>Подарочные сертификаты</a>
        </div>
        <div>
          <h4>Покупателю</h4>
          <a>Контакты</a>
          <a>Вакансии</a>
          <a href="delivery.html">Доставка</a>
          <a href="payment.html">Оплата</a>
        </div>
        <div>
          <h4>Информация</h4>
          <a href="news.html">Блог</a>
          <a>Бренды</a>
          <a href="terms.html">Пользовательское соглашение</a>
          <a href="privacy.html">Политика конфиденциальности</a>
        </div>
      </div>
      <div className="sub">2026 © Печной Эксперт</div>
    </footer>
  );
}

// ===== PRODUCT PLACEHOLDER (bag icon — stands in for real product photo) =====
function ProductPlaceholder({ variant = 0, label = '' }) {
  return (
    <div style={{width:'100%',height:'100%',display:'flex',alignItems:'center',justifyContent:'center',background:'#fff'}}>
      <img src="shared/placeholder-bag.png" alt={label || 'фото товара'}
           style={{width:'70%',height:'70%',objectFit:'contain',display:'block'}}/>
    </div>
  );
}

// ===== ACCOUNT SUBNAV =====
// Навигация по разделам личного кабинета. Отображается на всех страницах ЛК.
// Реализована как горизонтальная полоса из 5 кнопок-дропдаунов
// (b2b-паттерн: компактно, привычно). Каждая кнопка — название группы;
// по клику разворачивается меню со ссылками раздела. Кнопка группы,
// в которой лежит активный раздел, подсвечивается белой капсулой;
// внутри меню активный пункт тоже выделен.
// active — id текущего раздела:
//   cart | orders | frequent | compare |
//   reports | act | upd |
//   addr-delivery | tk | addr-stores |
//   profile | orgs | staff |
//   notify | claims
function SubNav({ active }) {
  const groups = [
    { id: 'product', title: 'Продукт', items: [
      { id: 'cart',          label: 'Корзина',                href: 'cart.html' },
      { id: 'orders',        label: 'Заказы',                 href: 'orders.html' },
      { id: 'frequent',      label: 'Частые покупки',         href: 'frequent.html' },
      { id: 'compare',       label: 'Сравнение',              href: 'compare.html' },
    ]},
    { id: 'finance', title: 'Финансы', items: [
      { id: 'reports',       label: 'Отчёты',                 href: 'reports.html' },
      { id: 'act',           label: 'Акт сверки',             href: 'act.html' },
      { id: 'upd',           label: 'УПД',                    href: 'upd.html' },
    ]},
    { id: 'logistics', title: 'Логистика', items: [
      { id: 'addr-delivery', label: 'Адреса доставки',        href: '#' },
      { id: 'tk',            label: 'Транспортные компании',  href: '#' },
      { id: 'addr-stores',   label: 'Адреса магазинов',       href: '#' },
    ]},
    { id: 'legal', title: 'Юридическое взаимодействие', items: [
      { id: 'profile',       label: 'Профиль',                href: '#' },
      { id: 'orgs',          label: 'Организации',            href: 'organizations.html' },
      { id: 'staff',         label: 'Сотрудники',             href: 'employees.html' },
    ]},
    { id: 'misc', title: 'Прочее', items: [
      { id: 'notify',        label: 'Уведомления',            href: '#' },
      { id: 'claims',        label: 'Рекламации',             href: 'claims.html' },
    ]},
  ];

  const [openId, setOpenId] = React.useState(null);
  const rootRef = React.useRef(null);
  const isMobile = typeof useIsMobile === 'function' ? useIsMobile() : false;

  React.useEffect(() => {
    if (!openId) return;
    const onDocClick = (e) => {
      if (rootRef.current && !rootRef.current.contains(e.target)) setOpenId(null);
    };
    const onKey = (e) => { if (e.key === 'Escape') setOpenId(null); };
    document.addEventListener('mousedown', onDocClick);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('mousedown', onDocClick);
      document.removeEventListener('keydown', onKey);
    };
  }, [openId]);

  // На мобиле .account-subnav горизонтально скроллится (overflow-x:auto),
  // из-за чего абсолютно-позиционированная выпадашка внутри группы
  // обрезается по вертикали (overflow:auto клипает оба направления).
  // Поэтому на мобиле меню открытой группы рендерим соседом — отдельной
  // плашкой ниже строки триггеров, вне скролл-контейнера.
  const openGroup = groups.find(g => g.id === openId) || null;

  return (
    <div className="account-subnav-wrap" ref={rootRef}>
      <nav className="account-subnav" aria-label="Разделы личного кабинета">
        {groups.map(g => {
          const isActiveGroup = g.items.some(it => it.id === active);
          const isOpen = openId === g.id;
          return (
            <div key={g.id} className={'account-subnav-group' + (isOpen ? ' open' : '')}>
              <button
                type="button"
                className={'account-subnav-trigger' + (isActiveGroup ? ' on' : '')}
                aria-expanded={isOpen}
                aria-haspopup="menu"
                onClick={() => setOpenId(isOpen ? null : g.id)}
              >
                <span>{g.title}</span>
                <svg className="account-subnav-chevron" width="10" height="6" viewBox="0 0 10 6" aria-hidden="true">
                  <path d="M1 1l4 4 4-4" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              </button>
              {isOpen && !isMobile && (
                <div className="account-subnav-menu" role="menu">
                  {g.items.map(it => (
                    <a
                      key={it.id}
                      href={it.href}
                      role="menuitem"
                      className={it.id === active ? 'on' : ''}
                    >
                      {it.label}
                    </a>
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </nav>
      {openGroup && isMobile && (
        <div className="account-subnav-mobile-menu" role="menu" aria-label={openGroup.title}>
          {openGroup.items.map(it => (
            <a
              key={it.id}
              href={it.href}
              role="menuitem"
              className={it.id === active ? 'on' : ''}
            >
              {it.label}
            </a>
          ))}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { Icon, Logo, Header, HeaderDesktop, Breadcrumbs, Footer, FooterDesktop, ProductPlaceholder, SubNav, useIsMobile });
