// app.jsx — root. Fetches the reservation, builds per-room stays for the chosen
// language, loads live weather, and renders the dashboard layout. (The prototype's
// design Tweaks panel and layout/theme/density switches are dropped for guests;
// the language switcher stays.)
const { useState, useEffect, useMemo } = React;

const LAYOUT = window.LayoutDashboard;   // chosen guest layout
const THEME = 'light';                   // forest/dark mode is design-only

function useNarrow() {
  const [narrow, setNarrow] = useState(typeof window !== 'undefined' && window.innerWidth < 860);
  useEffect(() => {
    const on = () => setNarrow(window.innerWidth < 860);
    window.addEventListener('resize', on);
    return () => window.removeEventListener('resize', on);
  }, []);
  return narrow;
}

function showFatal(message, opts) {
  opts = opts || {};
  const err = document.getElementById('error-screen');
  const title = document.getElementById('error-title');
  const msg = document.getElementById('error-message');
  const retry = document.getElementById('error-retry');
  if (title && opts.title) title.textContent = opts.title;
  if (msg) msg.textContent = message || 'We couldn’t load your reservation details.';
  // Retry is pointless for an auth failure — hide the button in that case.
  if (retry) retry.style.display = opts.retry === false ? 'none' : '';
  if (err) err.classList.remove('hidden');
}
function hideLoading() {
  // Use the loader's own teardown when available (also clears its phrase timer)...
  if (typeof window.__hideLoader === 'function') {
    try { window.__hideLoader(); } catch (e) {}
  }
  // ...but always remove the element directly too. The inline loader script can
  // fail to define __hideLoader (stale cache, CSP, a parse error) — and since the
  // loader sits at z-index 9999 it would otherwise cover the app AND the error
  // screen, leaving the page stuck on "loading" with no visible error.
  const ms = document.getElementById('ms-loader');
  if (ms) {
    ms.classList.add('is-done');
    setTimeout(() => { if (ms.parentNode) ms.parentNode.removeChild(ms); }, 600);
  }
  const legacy = document.getElementById('loading-screen'); // pre-redesign id, for any cached page
  if (legacy) legacy.classList.add('hidden');
}

function App({ payload }) {
  const [lang, setLangState] = useState(() => {
    try {
      const saved = localStorage.getItem('mp_lang');
      const avail = window.availableLanguages(payload);
      if (saved && avail.includes(saved)) return saved;
    } catch (e) {}
    return 'en';
  });
  const setLang = (l) => {setLangState(l);try {localStorage.setItem('mp_lang', l);} catch (e) {}};

  // Live weather keyed by "lat,lon" — fetched once per unique coordinate.
  const [weather, setWeather] = useState({});

  const narrow = useNarrow();

  useEffect(() => {
    const rtl = window.isRTL(lang);
    document.documentElement.lang = lang;
    document.documentElement.dir = rtl ? 'rtl' : 'ltr';
  }, [lang]);

  // Fetch weather for every distinct coordinate in the reservation.
  useEffect(() => {
    const stays = window.buildStays(payload, 'en');
    const seen = {};
    stays.forEach((s) => {
      if (s._wkey && !seen[s._wkey]) {
        seen[s._wkey] = true;
        window.fetchWeather(s._coords.lat, s._coords.lon).then((w) => {
          if (w) setWeather((prev) => ({ ...prev, [s._wkey]: w }));
        });
      }
    });
  }, [payload]);

  // Rebuild stays whenever the language changes; merge in live weather + label.
  const stays = useMemo(() => {
    const built = window.buildStays(payload, lang);
    return built.map((s) => {
      const w = s._wkey && weather[s._wkey];
      if (!w) return s;
      const info = window.weatherInfo(w.code, lang);
      return { ...s, weather: { tempC: w.tempC, kind: info.kind, label: info.label } };
    });
  }, [payload, lang, weather]);

  if (!stays.length) return null;
  const reservationStay = stays[0]; // reservation-level info is shared across rooms

  return (
    <window.LangCtx.Provider value={{ lang, setLang }}>
      <div data-theme={THEME} dir={window.isRTL(lang) ? 'rtl' : 'ltr'} style={{ minHeight: '100vh', background: 'var(--bg)', color: 'var(--fg)', fontFamily: 'var(--font-mono)' }}>
        <LAYOUT stay={reservationStay} stays={stays} showImage={true} density="compact" narrow={narrow} availableNow={reservationStay.availableNow} />
      </div>
    </window.LangCtx.Provider>);

}

// Farewell screen for a stay that has ended (403 OUTSIDE_WINDOW, reason 'after').
// Green full-bleed, white flower illustration, and a discounted re-book link that
// carries the guest's cached language.
function PastStayScreen({ lang }) {
  const t = (k) => window.tr(lang, k);
  const rtl = window.isRTL(lang);
  const voucherUrl = `https://master.reserve-online.net/?voucher=TELLAFRIEND&lang=${encodeURIComponent(lang || 'en')}`;
  return (
    <div dir={rtl ? 'rtl' : 'ltr'} style={{
      minHeight: '100vh', background: 'var(--color-green-primary)', color: 'var(--color-cream)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      textAlign: 'center', padding: '48px 24px', fontFamily: 'var(--font-mono)'
    }}>
      <div style={{ flex: 1 }} />
      <span style={{ color: 'var(--color-cream)' }}><window.FlowerHand size={190} /></span>
      <h1 style={{
        fontFamily: 'var(--font-serif)', fontWeight: 300, textTransform: 'uppercase',
        fontSize: 'clamp(30px, 8vw, 46px)', letterSpacing: '0.01em', lineHeight: 1.05,
        color: 'var(--color-cream)', margin: '44px 0 0'
      }}>{t('stayEnded')}</h1>
      <p style={{
        fontSize: 15, lineHeight: 1.7, letterSpacing: '0.04em', color: 'rgba(249,244,234,0.72)',
        maxWidth: 440, margin: '20px 0 0'
      }}>{t('stayEndedBody')}</p>

      <div style={{ fontFamily: 'var(--font-accent)', fontStyle: 'italic', fontSize: 18, color: 'var(--color-cream)', margin: '56px 0 16px' }}>{t('stayEndedActually')}</div>
      <a href={voucherUrl} style={{
        display: 'block', width: 'min(560px, 100%)', boxSizing: 'border-box',
        background: 'var(--color-cream)', color: 'var(--color-green-primary)', textDecoration: 'none',
        padding: '22px 20px', fontSize: 'clamp(11px, 2.6vw, 14px)', letterSpacing: '0.14em',
        textTransform: 'uppercase', textAlign: 'center'
      }}>{t('stayEndedCta')}</a>

      <div style={{ flex: 1 }} />
      <div style={{ fontFamily: 'var(--font-serif)', fontWeight: 700, fontSize: 26, color: 'var(--color-cream)', marginTop: 40 }}>master</div>
    </div>);
}

// ── Boot ──────────────────────────────────────────────────────────
(async function boot() {
  try {
    const params = new URLSearchParams(window.location.search);
    const resId = params.get('res');
    const id = params.get('id');
    const token = params.get('token'); // signed access token (preferred over id)
    if (!resId) throw new Error('Reservation ID (res) is missing from the URL.');

    const payload = await window.loadReservation(resId, id, token);

    // Merge any admin-managed UI-string overrides before the first render.
    window.applyUiStrings(window.extractUiStrings(payload));

    // Expose the offered languages to the language switcher.
    window.PORTAL_LANGS = window.availableLanguages(payload);

    hideLoading();
    ReactDOM.createRoot(document.getElementById('root')).render(<App payload={payload} />);
  } catch (err) {
    console.error('Initialization Error:', err);
    hideLoading();
    if (err && err.code === 'UNAUTHORIZED') {
      showFatal(err.message, { title: 'Access not authorized', retry: false });
    } else if (err && err.code === 'OUTSIDE_WINDOW') {
      let lang = 'en';
      try { lang = localStorage.getItem('mp_lang') || 'en'; } catch (e) {}
      const tr = window.tr;
      if (err.reason === 'after') {
        // Stay has ended → the farewell + re-book screen (rendered into #root).
        ReactDOM.createRoot(document.getElementById('root')).render(<PastStayScreen lang={lang} />);
      } else {
        let when = '';
        try {
          when = new Intl.DateTimeFormat(lang === 'he' ? 'he-IL' : 'en-GB', {
            timeZone: err.timeZone || undefined,
            weekday: 'long', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit',
          }).format(new Date(err.availableFrom));
        } catch (e) {}
        showFatal(tr(lang, 'opensOn', { when }), { title: tr(lang, 'stayNotStarted'), retry: false });
      }
    } else {
      showFatal(err && err.message);
    }
  }
})();
