// app.jsx — Production SPA mount.
// Differences from designer's preview:
//   - Role-bar (Лендинг/Кабинет/Заказ/Админ) скрыт (см. spa.html CSS).
//   - Tweaks-панель не рендерится.
//   - Текущая роль определяется URL: / → landing, /account → cabinet,
//     /order/new → wizard, /admin → admin (вместо useState('landing')).
//   - window.__nav делает реальный history.pushState.

const DEFAULT_TWEAKS = {
  theme: 'obsidian',
  displayFont: 'Instrument Serif',
  accent: ['#d4a574', '#c47a8a', '#7a8fc4', '#8aa896'],
  chartGlow: true,
  noiseEnabled: true,
};

const PATH_TO_ROLE = (path) => {
  if (path.startsWith('/order/new')) return 'wizard';
  if (path.startsWith('/account')) return 'cabinet';
  if (path.startsWith('/admin')) return 'admin';
  if (path.startsWith('/matrica')) return 'matrica';
  if (path === '/' || path === '' || path === '/index.html') return 'landing';
  // Любой неизвестный путь обслуживается тем же spa.html (сервер отдаёт его
  // со статусом 404 для навигации браузера) → рендерим интегрированную 404.
  return 'notfound';
};

const ROLE_TO_PATH = (role) => ({
  landing: '/',
  cabinet: '/account',
  wizard:  '/order/new',
  admin:   '/admin',
  matrica: '/matrica',
}[role] || '/');

// ——— Каталог продуктов: цены/названия тянутся с бэка (/api/catalog),
// чтобы не хардкодить их в компонентах. Заполняется в App, читается везде. ———
window.__catalog = window.__catalog || {};
const catalogPrice = (key, fallback) => {
  const c = window.__catalog[key];
  return c && typeof c.price_rub === 'number' ? c.price_rub : fallback;
};
const catalogTitle = (key, fallback) => {
  const c = window.__catalog[key];
  return c && c.title ? c.title : fallback;
};
const rubFmt = (n) => new Intl.NumberFormat('ru-RU').format(n) + ' ₽';

// Настройки сайта (реквизиты/контакты) — тянем с бэка, не хардкодим в компонентах.
window.__settings = window.__settings || {};
const setting = (key, fb) => {
  const v = window.__settings[key];
  return (v !== undefined && v !== '') ? v : (fb || '');
};

const ApplyTweaks = ({ t }) => {
  React.useEffect(() => {
    const root = document.documentElement;
    root.dataset.theme = t.theme;
    const a = Array.isArray(t.accent) ? t.accent : DEFAULT_TWEAKS.accent;
    if (t.theme === 'obsidian') {
      root.style.setProperty('--gold', a[0]);
      root.style.setProperty('--rose', a[1]);
      root.style.setProperty('--celest', a[2]);
      root.style.setProperty('--sage', a[3]);
    } else {
      root.style.removeProperty('--gold');
      root.style.removeProperty('--rose');
      root.style.removeProperty('--celest');
      root.style.removeProperty('--sage');
    }
    root.style.setProperty('--noise-opacity', t.noiseEnabled ? (t.theme === 'aurum' ? '0.04' : '0.06') : '0');
    root.style.setProperty('--font-display', `'${t.displayFont}', serif`);
  }, [t]);
  return null;
};

const App = () => {
  const [role, setRole] = React.useState(PATH_TO_ROLE(window.location.pathname));
  const [cabSub, setCabSub] = React.useState('home');
  const [admSub, setAdmSub] = React.useState('dashboard');

  // Один раз тянем каталог цен с бэка; setCatTick форсит ре-рендер дерева,
  // чтобы компоненты перечитали window.__catalog (с фолбэками до загрузки).
  const [, setCatTick] = React.useState(0);
  React.useEffect(() => {
    fetch('/api/catalog', { credentials: 'same-origin' })
      .then(r => r.json())
      .then(d => { (d.services || []).forEach(s => { window.__catalog[s.id] = s; }); setCatTick(x => x + 1); })
      .catch(() => {});
    fetch('/api/settings', { credentials: 'same-origin' })
      .then(r => r.json())
      .then(d => { window.__settings = d || {}; setCatTick(x => x + 1); })
      .catch(() => {});
  }, []);

  // popstate (back/forward buttons) syncs role
  React.useEffect(() => {
    const onPop = () => {
      setRole(PATH_TO_ROLE(window.location.pathname));
      window.scrollTo({ top: 0, behavior: 'auto' });
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  // Expose nav for buttons inside screens.
  // Landing — public, используем pushState (быстро, без перезагрузки).
  // Cabinet / Wizard / Admin — gated на сервере; делаем real navigation,
  // чтобы middleware успел редиректнуть гостя на /login?next=…
  React.useEffect(() => {
    window.__nav = (to) => {
      const path = ROLE_TO_PATH(to);
      if (to === 'landing') {
        if (window.location.pathname !== path) {
          window.history.pushState({}, '', path);
        }
        setRole(to);
        window.scrollTo({ top: 0, behavior: 'auto' });
        return;
      }
      // Gated routes — пусть Go-роутер сам решит, пускать или редиректить
      window.location.href = path;
    };
    // Logout helper used in cabinet/admin headers
    window.__logout = async () => {
      try { await fetch('/api/auth/logout', { method: 'POST', credentials: 'same-origin' }); } catch (_) {}
      window.location.href = '/login';
    };
  }, []);

  React.useEffect(() => {
    // Honor an anchor hash on the public landing (e.g. arriving at /#catalog
    // from the matrix page navbar). Sections mount after in-browser Babel
    // boots, so poll a few frames for the target before giving up.
    if (role === 'landing' && window.location.hash.length > 1) {
      const id = decodeURIComponent(window.location.hash.slice(1));
      let frames = 0;
      const seek = () => {
        const el = document.getElementById(id);
        if (el) { el.scrollIntoView({ behavior: 'auto', block: 'start' }); return; }
        if (frames++ < 60) requestAnimationFrame(seek);
      };
      requestAnimationFrame(seek);
      return;
    }
    window.scrollTo({ top: 0, behavior: 'auto' });
  }, [role, cabSub, admSub]);

  return (
    <>
      <ApplyTweaks t={DEFAULT_TWEAKS} />
      {role === 'landing'  && <Landing />}
      {role === 'matrica'  && <MatrixLanding />}
      {role === 'cabinet'  && <Cabinet subPage={cabSub} onSubPage={setCabSub} />}
      {role === 'wizard'   && <Wizard />}
      {role === 'admin'    && <Admin subPage={admSub} onSubPage={setAdmSub} />}
      {role === 'notfound' && <NotFound />}
    </>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
