/* ============================================================
   APP — router, tweaks, mount
   ============================================================ */
const { useState, useEffect } = React;
const PAGES = ['home', 'snorkeling', 'diving', 'speedboat', 'private_boat', 'explained', 'faq', 'contact'];

/* ---- Clean-URL routing: single source of truth ---------------------------- */
/* clean path  ->  internal page key (keys must NOT be renamed) */
const PATH_TO_KEY = {
  '/': 'home',
  '/dolphin-house-hurghada': 'snorkeling',
  '/dolphin-with-diving-hurghada': 'diving',
  '/private-speedboat-dolphin-house-hurghada': 'speedboat',
  '/private-boat-dolphin-house-hurghada': 'private_boat',
  '/dolphin-house-explained': 'explained',
  '/faq': 'faq',
  '/book-now': 'contact',
  // '/compare' retired — server 301-redirects it to '/' (and '/xx/compare' → '/xx').
};
/* derived: internal key -> clean path */
const KEY_TO_PATH = Object.keys(PATH_TO_KEY).reduce((m, p) => { m[PATH_TO_KEY[p]] = p; return m; }, {});

/* legacy hash -> clean path (back-compat shim) */
const HASH_TO_PATH = {
  'home': '/',
  'snorkeling': '/dolphin-house-hurghada',
  'diving': '/dolphin-with-diving-hurghada',
  'speedboat': '/private-speedboat-dolphin-house-hurghada',
  'private': '/private-boat-dolphin-house-hurghada',
  'private_boat': '/private-boat-dolphin-house-hurghada',
  'explained': '/dolphin-house-explained',
  'compare': '/',
  'faq': '/faq',
  'contact': '/book-now',
  'book': '/book-now',
};

function normalizePath(p) {
  if (!p) return '/';
  // strip query/hash
  p = p.split('?')[0].split('#')[0];
  // strip trailing slash except root
  if (p.length > 1 && p.endsWith('/')) p = p.slice(0, -1);
  return p;
}

/* ---- Language-prefix helpers (delegated to I18N, with safe fallbacks) ---- */
/* Split a pathname into { lang, cleanPath }. A leading "/xx" for a supported
   non-EN code is the language prefix; English has none. */
function splitLangPath(p) {
  if (window.I18N && typeof window.I18N.splitLangPath === 'function') {
    return window.I18N.splitLangPath(p);
  }
  return { lang: 'en', cleanPath: normalizePath(p) };
}
/* Current active language (from I18N). */
function curLang() {
  return (window.I18N && window.I18N.lang) || 'en';
}
/* Prepend the (given or current) language prefix to a clean path. */
function withLangPrefix(cleanPath, code) {
  if (code == null) code = curLang();
  if (window.I18N && typeof window.I18N.withLangPrefix === 'function') {
    return window.I18N.withLangPrefix(cleanPath, code);
  }
  return cleanPath;
}

function keyFromPath(p) {
  return PATH_TO_KEY[splitLangPath(p).cleanPath] || 'home';
}
/* Internal key → clean (English) path, WITHOUT language prefix. */
function pathFromKey(k) {
  return KEY_TO_PATH[k] || '/';
}
/* Internal key → full pathname INCLUDING the current language prefix. */
function localizedPathFromKey(k, code) {
  return withLangPrefix(pathFromKey(k), code);
}

/* Slug (clean path segment, no leading slash) -> trip key, e.g.
   'dolphin-house-hurghada' -> 'snorkeling'. Reuses PATH_TO_KEY. */
function tripKeyFromSlug(slug) {
  return PATH_TO_KEY['/' + String(slug || '').replace(/^\//, '')] || null;
}

/* Resolve a full pathname into a route descriptor:
   { page:'home'|'book'|'confirmation'|<trip>|..., param:<string|null> }
   Side effect: syncs I18N.lang from the URL language prefix (URL wins).
   Checkout/confirmation routes are NEVER language-prefixed (left as-is). */
function resolveRoute(pathname) {
  const raw = normalizePath(pathname);
  // Checkout + confirmation: no language prefix, do not touch lang here.
  if (raw.indexOf('/book/') === 0) {
    const slug = raw.slice('/book/'.length);
    return { page: 'book', param: tripKeyFromSlug(slug) };
  }
  if (raw.indexOf('/booking-confirmation/') === 0) {
    const ref = raw.slice('/booking-confirmation/'.length);
    return { page: 'confirmation', param: ref || null };
  }
  // Split off any language prefix and sync I18N.lang to it (URL authoritative).
  const split = splitLangPath(raw);
  if (window.I18N && window.I18N.lang !== split.lang &&
      typeof window.I18N.setLangSilent === 'function') {
    window.I18N.setLangSilent(split.lang);
  }
  return { page: PATH_TO_KEY[split.cleanPath] || 'home', param: null };
}

/* Crawlable internal link — renders a real <a href> (with the current
   language prefix) but navigates via go() */
function Link({ to, children, ...rest }) {
  const href = localizedPathFromKey(to);
  return (
    <a href={href} onClick={(e) => {
      if (e.metaKey || e.ctrlKey || e.shiftKey || e.button) return;
      e.preventDefault();
      window.go(to);
    }} {...rest}>{children}</a>
  );
}

/* expose routing helpers globally for use across jsx files */
Object.assign(window, { PATH_TO_KEY, KEY_TO_PATH, pathFromKey, localizedPathFromKey, keyFromPath, tripKeyFromSlug, resolveRoute, splitLangPath, withLangPrefix, curLang, Link });

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "hero": "immersive",
  "picker": "cards",
  "accent": "#ff6a43",
  "sea": "#10b6cd"
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  // Remove the first-paint boot skeleton once mounted (deterministic, regardless
  // of how createRoot handles existing container markup).
  useEffect(() => {
    const b = document.getElementById('boot');
    if (b) b.remove();
  }, []);
  // i18n: re-render the whole tree when the language changes
  const [, setI18nLang] = useState(window.I18N ? window.I18N.lang : 'en');
  useEffect(() => {
    if (window.I18N) window.I18N._onChange = setI18nLang;
    return () => { if (window.I18N) window.I18N._onChange = null; };
  }, []);
  const [route, setRoute] = useState(() => {
    // 1) legacy hash present on load → migrate to clean path
    const h = (window.location.hash || '').replace('#', '');
    if (h && HASH_TO_PATH[h]) {
      const clean = HASH_TO_PATH[h];
      try { history.replaceState(null, '', clean); } catch (e) {}
      return resolveRoute(clean);
    }
    // 2) URL pathname is authoritative (no localStorage restore)
    return resolveRoute(window.location.pathname);
  });
  const page = route.page;

  const go = (p) => {
    if (!PAGES.includes(p)) p = 'home';
    setRoute({ page: p, param: null });
    try { localStorage.setItem('dh_page', p); } catch (e) {}
    // Push the path WITH the current language prefix (en → no prefix).
    try { history.pushState(null, '', localizedPathFromKey(p)); } catch (e) {}
    window.scrollTo({ top: 0, behavior: 'auto' });
  };

  // Navigate to a parameterized clean path (e.g. '/book/<slug>?date=…',
  // '/booking-confirmation/<ref>'). Keeps query string in the URL but the
  // page/param are derived from the pathname.
  const goPath = (fullPath) => {
    const path = '/' + String(fullPath || '/').replace(/^\//, '');
    setRoute(resolveRoute(path));
    try { history.pushState(null, '', path); } catch (e) {}
    window.scrollTo({ top: 0, behavior: 'auto' });
  };

  // expose for Link + cross-file callers
  window.go = go;
  window.goPath = goPath;

  // browser back/forward → re-derive route from pathname
  useEffect(() => {
    const onPop = () => setRoute(resolveRoute(window.location.pathname));
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  // apply color tweaks to CSS variables
  useEffect(() => {
    const r = document.documentElement.style;
    r.setProperty('--coral', t.accent);
    r.setProperty('--accent', t.accent);
    r.setProperty('--turq', t.sea);
  }, [t.accent, t.sea]);

  const tw = { hero: t.hero, picker: t.picker };
  // Header theme model: the fixed header may render as transparent with light
  // (white) text ONLY while it sits over a known DARK hero. Pages whose top is
  // light/cream (editorial home hero, the /book/* checkout, and the
  // /booking-confirmation/* page) have NO dark hero behind the header, so the
  // header must use dark text. (Scrolled state is handled separately in Header.)
  const lightTopPages = page === 'book' || page === 'confirmation' || (page === 'home' && t.hero === 'editorial');
  const heroDark = !lightTopPages;
  const productTrip = DATA.trips[page] || null;

  let content;
  if (page === 'book') content = <CheckoutPage tripKey={route.param} go={go} goPath={goPath} query={window.location.search}/>;
  else if (page === 'confirmation') content = <ConfirmationPage reference={route.param} go={go} goPath={goPath}/>;
  else if (page === 'home') content = <Home go={go} tw={tw}/>;
  else if (productTrip) content = <ProductPage tripKey={page} go={go}/>;
  else if (page === 'faq') content = <FaqPage go={go}/>;
  else if (page === 'explained') content = <ExplainedPage go={go}/>;
  else if (page === 'contact') content = <ContactPage go={go}/>;
  else content = <Home go={go} tw={tw}/>;

  return (
    <>
      <Header page={page} go={go} heroDark={heroDark}/>
      {content}
      <Footer go={go}/>
      <StickyCTA trip={productTrip} page={page}/>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Homepage hero"/>
        <TweakRadio label="Hero style" value={t.hero} options={['immersive', 'editorial']} onChange={(v) => setTweak('hero', v)}/>
        <TweakSection label="Trip picker"/>
        <TweakRadio label="Layout" value={t.picker} options={['cards', 'board']} onChange={(v) => setTweak('picker', v)}/>
        <TweakSection label="Colour"/>
        <TweakColor label="Accent (coral)" value={t.accent} options={['#ff6a43', '#ff4d6d', '#ff8a3d', '#e8536b']} onChange={(v) => setTweak('accent', v)}/>
        <TweakColor label="Sea energy" value={t.sea} options={['#10b6cd', '#0bb39e', '#1f9be0', '#19c2c2']} onChange={(v) => setTweak('sea', v)}/>
        <div style={{ padding: '4px 2px 2px', fontSize: 12, color: '#8aa0a6', lineHeight: 1.5 }}>
          Toggle hero &amp; picker to compare the two booking-card directions. Colours update the live accent &amp; sea energy across the whole site.
        </div>
      </TweaksPanel>
    </>
  );
}

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