/* Volaire — shared UI: router, icons, atoms, header, footer, layout */
const { useState, useEffect, useRef, useMemo, useCallback } = React;
const L = window.VolaireLib;
const { useLang } = window.VolaireI18n;

/* ---------- hash router ---------- */
function parseHash() {
  let h = window.location.hash.replace(/^#/, '') || '/';
  const qi = h.indexOf('?');
  let query = {};
  if (qi >= 0) {
    const qs = new URLSearchParams(h.slice(qi + 1));
    qs.forEach(function (v, k) { query[k] = v; });
    h = h.slice(0, qi);
  }
  if (!h.startsWith('/')) h = '/' + h;
  return { path: h, query: query };
}
function navigate(to) {
  window.location.hash = to;
  window.scrollTo(0, 0);
}
function useRoute() {
  const [route, setRoute] = useState(parseHash());
  useEffect(function () {
    const fn = function () { setRoute(parseHash()); };
    window.addEventListener('hashchange', fn);
    return function () { window.removeEventListener('hashchange', fn); };
  }, []);
  return route;
}
function Link(props) {
  const { to, className, children, onClick } = props;
  return (
    <a
      href={'#' + to}
      className={className}
      aria-label={props['aria-label']}
      onClick={function (e) {
        if (onClick) onClick(e);
        if (!e.defaultPrevented) {
          e.preventDefault();
          navigate(to);
        }
      }}
    >{children}</a>
  );
}

/* ---------- session hook ---------- */
function useSession() {
  const [session, setSessionState] = useState(L.getSession());
  useEffect(function () {
    const fn = function () { setSessionState(L.getSession()); };
    window.addEventListener('volaire:session', fn);
    return function () { window.removeEventListener('volaire:session', fn); };
  }, []);
  return session;
}

/* ---------- icons (inline SVG, stroke style) ---------- */
const ICON_PATHS = {
  globe: <g><circle cx="12" cy="12" r="9"></circle><path d="M3 12h18M12 3c2.5 2.6 3.8 5.7 3.8 9S14.5 18.4 12 21c-2.5-2.6-3.8-5.7-3.8-9S9.5 5.6 12 3z"></path></g>,
  user: <g><circle cx="12" cy="8" r="4"></circle><path d="M4 20c1.5-3.5 4.5-5 8-5s6.5 1.5 8 5"></path></g>,
  plane: <g><path d="M10.5 13.5L4 11l1.5-1.5L11 10l4.5-4.5c.8-.8 2.2-.8 3 0s.8 2.2 0 3L14 13l.5 5.5L13 20l-2.5-6.5z"></path></g>,
  planeUp: <g><path d="M3 19h18M5 15l13.5-6.2c1-.5 1.5-1.6 1-2.6-.4-.9-1.5-1.3-2.4-.9L13 7.5 7 5 5.5 6.5 10 9.5l-4 2-2.5-1L2 12l3 3z"></path></g>,
  bag: <g><rect x="6" y="8" width="12" height="12" rx="2"></rect><path d="M9 8V6a3 3 0 016 0v2"></path></g>,
  seat: <g><path d="M7 4v9a2 2 0 002 2h7"></path><path d="M7 13h7a3 3 0 013 3v4"></path><path d="M5 20h6"></path></g>,
  check: <path d="M5 12.5l4.5 4.5L19 7"></path>,
  cross: <path d="M6 6l12 12M18 6L6 18"></path>,
  info: <g><circle cx="12" cy="12" r="9"></circle><path d="M12 11v5"></path><circle cx="12" cy="8" r="0.5" fill="currentColor"></circle></g>,
  chevronDown: <path d="M6 9l6 6 6-6"></path>,
  chevronRight: <path d="M9 6l6 6-6 6"></path>,
  arrowRight: <path d="M4 12h16m-6-6l6 6-6 6"></path>,
  swap: <path d="M7 4v13m0 0l-3-3m3 3l3-3M17 20V7m0 0l-3 3m3-3l3 3"></path>,
  calendar: <g><rect x="4" y="6" width="16" height="14" rx="2"></rect><path d="M4 10h16M8 4v4M16 4v4"></path></g>,
  clock: <g><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5l3 3"></path></g>,
  shield: <g><path d="M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3z"></path><path d="M9 12l2 2 4-4"></path></g>,
  card: <g><rect x="3" y="6" width="18" height="13" rx="2"></rect><path d="M3 10h18M7 15h4"></path></g>,
  help: <g><circle cx="12" cy="12" r="9"></circle><path d="M9.5 9.5a2.5 2.5 0 114 2c-.8.6-1.5 1-1.5 2.2"></path><circle cx="12" cy="17" r="0.5" fill="currentColor"></circle></g>,
  meal: <g><path d="M5 4v7a2 2 0 002 2v7M9 4v5M5 7h4M15 4c2.2 0 4 2.2 4 5s-1.8 5-4 5v6"></path></g>,
  bike: <g><circle cx="6" cy="16" r="3.5"></circle><circle cx="18" cy="16" r="3.5"></circle><path d="M6 16l4-7h5l3 7M10 9L8.5 6H11"></path></g>,
  star: <path d="M12 4l2.4 4.9 5.4.8-3.9 3.8.9 5.4-4.8-2.5-4.8 2.5.9-5.4L4.2 9.7l5.4-.8L12 4z"></path>,
  lock: <g><rect x="5" y="11" width="14" height="9" rx="2"></rect><path d="M8 11V8a4 4 0 018 0v3"></path></g>,
  phone: <g><rect x="7" y="3" width="10" height="18" rx="2.5"></rect><path d="M10.5 18.5h3"></path></g>,
  doc: <g><path d="M7 3h7l4 4v14H7V3z"></path><path d="M14 3v4h4M10 12h6M10 16h6"></path></g>,
  wallet: <g><path d="M4 7a2 2 0 012-2h12a2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V7z"></path><path d="M16 13h4v-3h-4a1.5 1.5 0 000 3z"></path></g>,
};
function Icon({ name, size, className }) {
  return (
    <svg viewBox="0 0 24 24" width={size || 20} height={size || 20} fill="none" stroke="currentColor"
      strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"
      className={className} aria-hidden="true">{ICON_PATHS[name] || null}</svg>
  );
}

/* ---------- logo: lowercase wordmark, wing-tick on the i ---------- */
function VolaireMark({ height, light }) {
  const h = height || 26;
  return (
    <svg viewBox="0 0 132 34" height={h} aria-label="Volaire" role="img" className="block">
      <text x="0" y="26" fontFamily="Inter, sans-serif" fontWeight="800" fontSize="26"
        letterSpacing="-0.8" fill={light ? '#FFFFFF' : '#2042C8'}>vola<tspan fill={light ? '#FFFFFF' : '#2042C8'}>ı</tspan>re</text>
      {/* wing-tick replacing the dot of the i (the dotless ı above) */}
      <path d="M86.5 8.5 C89 5.5 93.5 3.6 97.5 3.2 C94.5 6 91 7.8 88.2 8.9 Z"
        fill={light ? '#FF8A7E' : '#FF6A5C'}></path>
    </svg>
  );
}

/* ---------- atoms ---------- */
function Badge({ variant, children, className }) {
  const variants = {
    coral: 'bg-coral text-white',
    coralSoft: 'bg-coral/10 text-coral',
    cobalt: 'bg-cobalt text-white',
    cobaltSoft: 'bg-cobalt/10 text-cobalt',
    gold: 'bg-gold/15 text-gold',
    danger: 'bg-danger/10 text-danger',
    success: 'bg-success/10 text-success',
    neutral: 'bg-page text-muted',
  };
  return (
    <span className={'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide ' + (variants[variant] || variants.neutral) + ' ' + (className || '')}>{children}</span>
  );
}

function StatusPill({ status }) {
  const { t } = useLang();
  const map = { confirmed: 'success', 'checked-in': 'cobaltSoft', completed: 'neutral', cancelled: 'danger' };
  return <Badge variant={map[status] || 'neutral'}>{t('account.trip.status.' + status)}</Badge>;
}

function PriceTag({ amount, from, size, className }) {
  const { t } = useLang();
  const sizes = { sm: 'text-sm', md: 'text-lg', lg: 'text-2xl', xl: 'text-3xl' };
  return (
    <span className={'inline-flex items-baseline gap-1 ' + (className || '')}>
      {from ? <span className="text-xs font-medium text-muted">{t('search.results.from')}</span> : null}
      <span className={'font-bold tabular-nums tracking-tight ' + (sizes[size || 'md'])}>{L.fmtEUR(amount)}</span>
    </span>
  );
}

function FareFamilyPill({ fare }) {
  const { t } = useLang();
  const map = { light: 'neutral', classic: 'cobaltSoft', flex: 'gold' };
  return <Badge variant={map[fare]}>{t('search.fare.' + fare)}</Badge>;
}

/* ---------- modal ---------- */
function Modal({ open, onClose, title, children }) {
  const { t } = useLang();
  useEffect(function () {
    if (!open) return;
    const fn = function (e) { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', fn);
    return function () { window.removeEventListener('keydown', fn); };
  }, [open]);
  if (!open) return null;
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4" role="dialog" aria-modal="true" aria-label={title}>
      <div className="absolute inset-0 bg-ink/40" onClick={onClose}></div>
      <div className="relative w-full max-w-md rounded-xl border border-line bg-white p-6 shadow-xl">
        <div className="flex items-start justify-between gap-4">
          <h2 className="text-lg font-bold tracking-tight text-ink">{title}</h2>
          <button onClick={onClose} aria-label={t('common.close')} className="rounded-lg p-1 text-muted hover:bg-page hover:text-ink"><Icon name="cross" size={18}></Icon></button>
        </div>
        <div className="mt-3">{children}</div>
      </div>
    </div>
  );
}

/* ---------- toast ---------- */
let toastListener = null;
function showToast(message) { if (toastListener) toastListener(message); }
function ToastHost() {
  const [toast, setToast] = useState(null);
  useEffect(function () {
    toastListener = function (m) {
      setToast(m);
      setTimeout(function () { setToast(null); }, 3200);
    };
    return function () { toastListener = null; };
  }, []);
  if (!toast) return null;
  return (
    <div className="fixed bottom-6 left-1/2 z-[60] -translate-x-1/2" role="status" aria-live="polite">
      <div className="flex items-center gap-2 rounded-xl bg-ink px-4 py-3 text-sm font-medium text-white shadow-lg">
        <span className="text-success"><Icon name="check" size={18}></Icon></span>{toast}
      </div>
    </div>
  );
}

/* ---------- breadcrumb ---------- */
function Breadcrumb({ items }) {
  return (
    <nav aria-label="Fil d’Ariane" className="flex flex-wrap items-center gap-1.5 text-sm text-muted">
      {items.map(function (it, i) {
        const last = i === items.length - 1;
        return (
          <span key={i} className="flex items-center gap-1.5">
            {it.to && !last ? <Link to={it.to} className="hover:text-cobalt hover:underline">{it.label}</Link>
              : <span className={last ? 'font-medium text-ink' : ''}>{it.label}</span>}
            {!last ? <Icon name="chevronRight" size={14} className="text-line"></Icon> : null}
          </span>
        );
      })}
    </nav>
  );
}

/* ---------- language switcher ---------- */
function LangSwitcher({ dark }) {
  const { lang, setLang } = useLang();
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(function () {
    const fn = function (e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('click', fn);
    return function () { document.removeEventListener('click', fn); };
  }, []);
  return (
    <div className="relative" ref={ref}>
      <button
        className={'flex items-center gap-1.5 rounded-lg px-2 py-1 text-xs font-semibold uppercase ' + (dark ? 'text-white/90 hover:bg-white/10' : 'text-muted hover:bg-page hover:text-ink')}
        aria-haspopup="listbox" aria-expanded={open} aria-label="Langue / Language"
        onClick={function () { setOpen(!open); }}>
        <Icon name="globe" size={14}></Icon>{lang.toUpperCase()}<Icon name="chevronDown" size={12}></Icon>
      </button>
      {open ? (
        <ul role="listbox" className="absolute right-0 top-full z-50 mt-1 w-36 overflow-hidden rounded-xl border border-line bg-white py-1 shadow-lg">
          {[{ c: 'fr', label: 'Français' }, { c: 'en', label: 'English' }, { c: 'es', label: 'Español' }].map(function (o) {
            return (
              <li key={o.c} role="option" aria-selected={lang === o.c}>
                <button
                  className={'flex w-full items-center justify-between px-3 py-2 text-sm hover:bg-page ' + (lang === o.c ? 'font-semibold text-cobalt' : 'text-ink')}
                  onClick={function () { window.VolaireI18n.setLang(o.c); setOpen(false); }}>
                  <span>{o.label}</span><span className="text-xs uppercase text-muted">{o.c}</span>
                </button>
              </li>
            );
          })}
        </ul>
      ) : null}
    </div>
  );
}

/* ---------- header ---------- */
function Header() {
  const { t } = useLang();
  const session = useSession();
  const route = useRoute();
  const nav = [
    { to: '/', label: t('nav.book'), active: route.path === '/' || route.path === '/search' || route.path === '/booking' },
    { to: '/account/trips', label: t('nav.trips'), active: route.path.startsWith('/account/trips') },
    { to: '/checkin', label: t('nav.checkin'), active: route.path === '/checkin' },
    { to: '/help', label: t('nav.help'), active: route.path.startsWith('/help') },
  ];
  return (
    <header className="sticky top-0 z-40 bg-white">
      <div className="border-b border-line bg-ink">
        <div className="mx-auto flex max-w-6xl items-center justify-between gap-4 px-4 py-1.5">
          <p className="truncate text-xs text-white/80">{t('topbar.checkinOpen')}</p>
          <div className="flex shrink-0 items-center gap-2">
            <LangSwitcher dark={true}></LangSwitcher>
            <Link to="/help" className="text-xs font-medium text-white/80 hover:text-white">{t('nav.help')}</Link>
          </div>
        </div>
      </div>
      <div className="border-b border-line">
        <div className="mx-auto flex max-w-6xl items-center justify-between gap-6 px-4 py-3">
          <Link to="/" aria-label="Volaire — accueil" className="shrink-0"><VolaireMark height={26}></VolaireMark></Link>
          <nav aria-label="Navigation principale" className="hidden items-center gap-1 md:flex">
            {nav.map(function (n) {
              return (
                <Link key={n.to} to={n.to}
                  className={'rounded-lg px-3 py-2 text-sm font-medium ' + (n.active ? 'bg-cobalt/10 text-cobalt' : 'text-ink hover:bg-page')}>
                  {n.label}
                </Link>
              );
            })}
          </nav>
          <div className="flex items-center gap-2">
            {session ? (
              <Link to="/account" className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-ink hover:bg-page" aria-label={t('nav.account')}>
                <span className="flex h-7 w-7 items-center justify-center rounded-full bg-cobalt text-xs font-bold text-white">{(session.firstName || 'C')[0]}</span>
                <span className="hidden sm:inline">{session.firstName}</span>
              </Link>
            ) : (
              <Link to="/login" className="flex items-center gap-2 rounded-lg border border-line px-3 py-2 text-sm font-semibold text-cobalt hover:border-cobalt">
                <Icon name="user" size={16}></Icon>{t('nav.signIn')}
              </Link>
            )}
          </div>
        </div>
        <nav aria-label="Navigation principale (mobile)" className="flex gap-1 overflow-x-auto px-4 pb-2 md:hidden">
          {nav.map(function (n) {
            return (
              <Link key={n.to} to={n.to}
                className={'shrink-0 rounded-lg px-3 py-1.5 text-sm font-medium ' + (n.active ? 'bg-cobalt/10 text-cobalt' : 'text-ink hover:bg-page')}>
                {n.label}
              </Link>
            );
          })}
        </nav>
      </div>
    </header>
  );
}

/* ---------- footer ---------- */
function FooterCol({ title, links }) {
  return (
    <div>
      <h3 className="text-xs font-bold uppercase tracking-wider text-muted">{title}</h3>
      <ul className="mt-3 flex flex-col gap-2">
        {links.map(function (l, i) {
          return <li key={i}><Link to={l.to || '/help'} className="text-sm text-ink hover:text-cobalt hover:underline">{l.label}</Link></li>;
        })}
      </ul>
    </div>
  );
}
function Footer() {
  const { t } = useLang();
  return (
    <footer className="mt-16 border-t border-line bg-white">
      <div className="mx-auto max-w-6xl px-4 py-10">
        <div className="grid grid-cols-2 gap-8 md:grid-cols-4">
          <FooterCol title={t('footer.service')} links={[
            { label: t('footer.contact'), to: '/help' },
            { label: t('help.baggage.link'), to: '/help/baggage' },
            { label: t('help.refunds.link'), to: '/help/refunds' },
            { label: t('nav.checkin'), to: '/checkin' },
          ]}></FooterCol>
          <FooterCol title={t('footer.company')} links={[
            { label: t('footer.about'), to: '/about' },
            { label: 'Volaire Club', to: '/account' },
            { label: t('nav.trips'), to: '/account/trips' },
          ]}></FooterCol>
          <FooterCol title={t('footer.legal')} links={[
            { label: t('footer.legal.imprint'), to: '/about' },
            { label: t('footer.legal.terms'), to: '/about' },
            { label: t('footer.legal.carriage'), to: '/about' },
            { label: t('footer.legal.privacy'), to: '/about' },
            { label: t('footer.legal.passengerRights'), to: '/help/refunds' },
          ]}></FooterCol>
          <div>
            <h3 className="text-xs font-bold uppercase tracking-wider text-muted">{t('footer.payment')}</h3>
            <div className="mt-3 flex items-center gap-2">
              {['VISA', 'MC', 'AMEX', 'PayPal'].map(function (p) {
                return <span key={p} className="rounded-md border border-line bg-page px-2 py-1 text-[10px] font-bold tracking-wide text-muted">{p}</span>;
              })}
            </div>
            <h3 className="mt-6 text-xs font-bold uppercase tracking-wider text-muted">{t('footer.trust')}</h3>
            <div className="mt-3 flex flex-col gap-2">
              <span className="flex items-center gap-2 text-sm text-muted"><span className="text-success"><Icon name="star" size={16}></Icon></span>{t('footer.verified')} · 4,6/5</span>
              <span className="flex items-center gap-2 text-sm text-muted"><Icon name="shield" size={16}></Icon>{t('footer.iata')}</span>
            </div>
          </div>
        </div>
        <div className="mt-10 flex flex-col items-start justify-between gap-4 border-t border-line pt-6 sm:flex-row sm:items-center">
          <div className="flex items-center gap-3">
            <VolaireMark height={20}></VolaireMark>
            <span className="text-sm italic text-muted">{t('brand.tagline')}</span>
          </div>
          <p className="text-xs text-muted">© 2026 Volaire SA — Compagnie fictive (démo). Toulouse, France.</p>
        </div>
      </div>
    </footer>
  );
}

/* ---------- destination tile w/ skyline ---------- */
const SKYLINES = {
  BCN: <path d="M0 40 L8 40 L8 26 L12 26 L12 40 L20 40 L24 18 L28 40 L34 40 L34 30 L40 30 L40 40 L50 40 L52 10 L54 22 L56 12 L58 24 L60 14 L62 40 L72 40 L72 28 L80 28 L80 40 L100 40"></path>,
  LIS: <path d="M0 40 L10 40 L10 30 L14 26 L18 30 L18 40 L28 40 L28 24 L32 20 L36 24 L36 40 L48 40 L48 32 L60 32 L60 40 L66 40 L66 16 L70 16 L70 40 L82 40 L86 34 L90 34 L100 40"></path>,
  FCO: <path d="M0 40 L8 40 L10 32 L14 32 L14 26 C14 22 20 22 20 26 L20 32 L24 32 L26 40 L38 40 L38 30 L42 30 L42 34 L46 34 L46 30 L50 30 L50 40 L62 40 L62 28 C62 22 72 22 72 28 L72 40 L84 40 L84 32 L92 32 L100 40"></path>,
  LHR: <path d="M0 40 L8 40 L8 30 L12 30 L12 40 L20 40 L20 20 L24 16 L28 20 L28 40 L36 40 L38 28 L42 28 L42 12 L44 8 L46 12 L46 28 L50 28 L52 40 L64 40 L64 26 L72 26 L72 40 L82 40 L82 22 C82 16 90 16 90 22 L90 40 L100 40"></path>,
  AMS: <path d="M0 40 L8 40 L8 26 L12 22 L16 26 L16 40 L24 40 L24 24 L28 20 L32 24 L32 40 L40 40 L40 28 L44 24 L48 28 L48 40 L58 40 L58 18 L62 14 L66 18 L66 40 L76 40 L76 30 L82 30 L82 40 L100 40"></path>,
  MAD: <path d="M0 40 L10 40 L10 28 L16 28 L16 40 L24 40 L24 14 L28 10 L32 14 L32 40 L42 40 L42 30 L50 30 L50 40 L58 40 L58 20 L64 20 L64 40 L74 40 L74 26 L78 22 L82 26 L82 40 L100 40"></path>,
  NCE: <path d="M0 40 L12 40 L12 32 L20 32 L20 40 L30 40 L30 28 L38 28 L38 40 L50 40 C56 32 64 32 70 40 L100 40"></path>,
};
function DestinationTile({ code, price, onSearch }) {
  const { lang, t } = useLang();
  const a = L.airportByCode[code];
  return (
    <button onClick={onSearch}
      className="group flex flex-col overflow-hidden rounded-xl border border-line bg-white text-left transition-colors hover:border-cobalt focus-visible:outline-cobalt"
      aria-label={L.cityName(a, lang) + ' — ' + t('home.destinations.from') + ' ' + L.fmtEUR(price)}>
      <div className="relative h-28 w-full overflow-hidden bg-gradient-to-b from-cobalt/15 via-sky/40 to-page">
        <svg viewBox="0 0 100 40" preserveAspectRatio="none" className="absolute bottom-0 left-0 h-16 w-full text-cobalt/50" fill="none" stroke="currentColor" strokeWidth="1.4">
          {SKYLINES[code] || SKYLINES.NCE}
        </svg>
      </div>
      <div className="flex items-center justify-between gap-2 p-4">
        <div>
          <p className="font-bold tracking-tight text-ink">{L.cityName(a, lang)}</p>
          <p className="text-xs text-muted">{a.code} · {a.name}</p>
        </div>
        <p className="text-sm font-semibold text-coral"><span className="font-medium text-muted">{t('home.destinations.from')} </span><span className="tabular-nums">{L.fmtEUR(price)}</span></p>
      </div>
    </button>
  );
}

/* ---------- form field ---------- */
function Field({ label, children, hint, className }) {
  return (
    <label className={'flex flex-col gap-1.5 ' + (className || '')}>
      <span className="text-xs font-semibold uppercase tracking-wide text-muted">{label}</span>
      {children}
      {hint ? <span className="text-xs text-muted">{hint}</span> : null}
    </label>
  );
}
const inputCls = 'w-full rounded-lg border border-line bg-white px-3 py-2.5 text-sm text-ink placeholder:text-muted/60 focus:border-cobalt focus:outline-none focus:ring-2 focus:ring-cobalt/20';

Object.assign(window, {
  parseHash, navigate, useRoute, Link, useSession,
  Icon, VolaireMark, Badge, StatusPill, PriceTag, FareFamilyPill,
  Modal, showToast, ToastHost, Breadcrumb, LangSwitcher,
  Header, Footer, DestinationTile, Field, inputCls, SKYLINES,
});
