// ============================================================
// AUTH + BOOKINGS — localStorage-backed user accounts and bookings.
// Demo-only: passwords stored in plaintext. Swap for a real backend
// (Firebase Auth, Supabase, etc.) before shipping.
// ============================================================
const AUTH_USERS_KEY = 'sh_users_v1';
const AUTH_SESSION_KEY = 'sh_session_v1';
const BOOKINGS_KEY = 'sh_bookings_v1';

function readJSON(key, fallback) {
  try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : fallback; }
  catch (_) { return fallback; }
}
function writeJSON(key, value) {
  try { localStorage.setItem(key, JSON.stringify(value)); } catch (_) {}
}

const AuthStore = {
  list() { return readJSON(AUTH_USERS_KEY, {}); },
  saveAll(users) { writeJSON(AUTH_USERS_KEY, users); },
  signup({ name, email, password }) {
    const users = AuthStore.list();
    const key = (email || '').trim().toLowerCase();
    if (!key || !password) throw new Error('Email and password required.');
    if (users[key]) throw new Error('An account with that email already exists.');
    users[key] = { name: (name || '').trim() || key.split('@')[0], email: key, password, createdAt: Date.now() };
    AuthStore.saveAll(users);
    AuthStore.setSession(key);
    return { name: users[key].name, email: key };
  },
  login({ email, password }) {
    const users = AuthStore.list();
    const key = (email || '').trim().toLowerCase();
    const u = users[key];
    if (!u || u.password !== password) throw new Error('Incorrect email or password.');
    AuthStore.setSession(key);
    return { name: u.name, email: u.email };
  },
  logout() { try { localStorage.removeItem(AUTH_SESSION_KEY); } catch (_) {} },
  setSession(email) { writeJSON(AUTH_SESSION_KEY, { email, at: Date.now() }); },
  currentEmail() { const s = readJSON(AUTH_SESSION_KEY, null); return s && s.email ? s.email : null; },
  currentUser() {
    const email = AuthStore.currentEmail();
    if (!email) return null;
    const u = AuthStore.list()[email];
    if (!u) return null;
    return { name: u.name, email: u.email };
  }
};
window.AuthStore = AuthStore;

const BookingStore = {
  all() { return readJSON(BOOKINGS_KEY, []); },
  forUser(email) {
    if (!email) return [];
    return BookingStore.all().filter(b => b.userEmail === email);
  },
  add(booking) {
    const all = BookingStore.all();
    const record = { id: `bk_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`, createdAt: Date.now(), ...booking };
    all.push(record);
    writeJSON(BOOKINGS_KEY, all);
    return record;
  }
};
window.BookingStore = BookingStore;

function useAuth() {
  const [user, setUser] = React.useState(() => AuthStore.currentUser());
  const refresh = React.useCallback(() => setUser(AuthStore.currentUser()), []);
  const signup = React.useCallback((data) => { const u = AuthStore.signup(data); refresh(); return u; }, [refresh]);
  const login = React.useCallback((data) => { const u = AuthStore.login(data); refresh(); return u; }, [refresh]);
  const logout = React.useCallback(() => { AuthStore.logout(); refresh(); }, [refresh]);
  return { user, signup, login, logout, refresh };
}
window.useAuth = useAuth;

function SmartImage({ src, alt, tone, label, className, style }) {
  const [failed, setFailed] = React.useState(false);
  if (failed || !src) {
    return (
      React.createElement('div', { className: 'img-placeholder', 'data-tone': tone || 'forest', style },
        React.createElement('div', { className: 'img-placeholder-label' }, label || alt || 'Image')
      )
    );
  }
  return React.createElement('img', { src, alt, className, style, loading: 'eager', decoding: 'async', fetchpriority: 'high', onError: () => setFailed(true) });
}
window.SmartImage = SmartImage;

function useReveal() {
  React.useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } });
    }, { threshold: 0.12 });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  }, []);
}
window.useReveal = useReveal;

// ============================================================
// RevealText — splits inline children into word spans for stagger reveal
// Accepts a mix of strings and React elements (e.g. <span class="accent">…</span>)
// ============================================================
function RevealText({ children, delay = 0, stagger = 45, autoplay = false, className = '' }) {
  const ref = React.useRef(null);
  const [revealed, setRevealed] = React.useState(false);

  React.useEffect(() => {
    if (autoplay) { setTimeout(() => setRevealed(true), delay); return; }
    if (!ref.current) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setRevealed(true); io.disconnect(); }
    }, { threshold: 0.3 });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [autoplay, delay]);

  // Build a flat list of {text, className, key} entries representing words.
  const words = [];
  let idx = 0;
  const pushString = (str, extraClass = '') => {
    const parts = str.split(/(\s+)/);
    parts.forEach((part) => {
      if (!part) return;
      if (/^\s+$/.test(part)) { words.push({ space: true }); }
      else { words.push({ text: part, idx: idx++, className: extraClass }); }
    });
  };

  React.Children.forEach(children, (child) => {
    if (typeof child === 'string' || typeof child === 'number') {
      pushString(String(child));
    } else if (React.isValidElement(child)) {
      const inner = child.props.children;
      if (typeof inner === 'string' || typeof inner === 'number') {
        pushString(String(inner), child.props.className || '');
      }
    }
  });

  return React.createElement('span', { ref, className: `reveal-text ${revealed ? 'in' : ''} ${className}` },
    words.map((w, k) => {
      if (w.space) return ' ';
      return React.createElement('span', { className: 'rt-word', key: k },
        React.createElement('span', {
          className: `rt-inner ${w.className || ''}`,
          style: { transitionDelay: `${delay + w.idx * stagger}ms` }
        }, w.text)
      );
    })
  );
}
window.RevealText = RevealText;

// ============================================================
// CountUp — count from 0 to `to` when scrolled into view
// ============================================================
function CountUp({ to, suffix = '', duration = 1400 }) {
  const [val, setVal] = React.useState(0);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {
        const start = performance.now();
        const animate = (now) => {
          const t = Math.min(1, (now - start) / duration);
          const eased = 1 - Math.pow(1 - t, 3);
          setVal(Math.round(to * eased));
          if (t < 1) requestAnimationFrame(animate);
        };
        requestAnimationFrame(animate);
        io.disconnect();
      }
    }, { threshold: 0.5 });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [to, duration]);
  return React.createElement('span', { ref }, val, suffix);
}
window.CountUp = CountUp;

// ============================================================
// Marquee — infinite horizontal scroll strip
// ============================================================
function Marquee({ items, speed = 50 }) {
  const doubled = [...items, ...items];
  return React.createElement('div', { className: 'marquee', style: { '--speed': `${speed}s` } },
    React.createElement('div', { className: 'marquee-track' },
      doubled.map((item, i) =>
        React.createElement('span', { className: 'marquee-item', key: i },
          React.createElement('span', { className: 'marquee-text' }, item),
          React.createElement('span', { className: 'marquee-dot', 'aria-hidden': 'true' }, '✦')
        )
      )
    )
  );
}
window.Marquee = Marquee;

// ============================================================
// useParallax — scroll-coupled Y translate
// ============================================================
function useParallax(ref, factor = 0.3) {
  React.useEffect(() => {
    if (!ref.current) return;
    let raf = null;
    const update = () => {
      raf = null;
      if (!ref.current) return;
      const rect = ref.current.getBoundingClientRect();
      const offset = -rect.top * factor;
      ref.current.style.transform = `translate3d(0, ${offset}px, 0) scale(${1 + Math.abs(rect.top) * 0.00003})`;
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(update); };
    update();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); if (raf) cancelAnimationFrame(raf); };
  }, [ref, factor]);
}
window.useParallax = useParallax;

// ============================================================
// MagneticButton — wraps a button so it gently follows the cursor
// ============================================================
function MagneticButton({ children, strength = 0.25, className = '', ...rest }) {
  const ref = React.useRef(null);
  const onMove = (e) => {
    const el = ref.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const x = (e.clientX - (rect.left + rect.width / 2)) * strength;
    const y = (e.clientY - (rect.top + rect.height / 2)) * strength;
    el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
  };
  const onLeave = () => { if (ref.current) ref.current.style.transform = ''; };
  return React.createElement('button', {
    ref, className: `magnetic ${className}`,
    onMouseMove: onMove, onMouseLeave: onLeave,
    ...rest
  }, children);
}
window.MagneticButton = MagneticButton;

const Icon = {
  Arrow: (props) => React.createElement('svg', { className: 'btn-arrow', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, ...props },
    React.createElement('path', { d: 'M5 12h14M13 5l7 7-7 7', strokeLinecap: 'round', strokeLinejoin: 'round' })
  ),
  Whatsapp: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'currentColor', ...props },
    React.createElement('path', { d: 'M17.5 14.4c-.3-.1-1.7-.8-2-.9-.3-.1-.5-.2-.7.2s-.8 1-.9 1.2c-.2.2-.3.2-.6.1-.3-.1-1.2-.5-2.3-1.4-.9-.7-1.5-1.7-1.6-2-.2-.3 0-.5.1-.6l.5-.5c.1-.2.2-.3.3-.5.1-.2 0-.4 0-.5-.1-.1-.7-1.7-1-2.3-.2-.6-.5-.5-.7-.5h-.6c-.2 0-.5.1-.8.4-.3.3-1 1-1 2.4 0 1.4 1 2.8 1.2 3 .1.2 2 3 4.8 4.2.7.3 1.2.5 1.6.6.7.2 1.3.2 1.8.1.6-.1 1.7-.7 1.9-1.3.2-.6.2-1.2.2-1.3-.1-.1-.3-.2-.6-.3M12 2C6.5 2 2 6.5 2 12c0 1.8.5 3.5 1.3 5L2 22l5.2-1.4c1.5.8 3.1 1.2 4.8 1.2 5.5 0 10-4.5 10-10S17.5 2 12 2' })
  ),
  Close: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, ...props },
    React.createElement('path', { d: 'M6 6l12 12M6 18L18 6', strokeLinecap: 'round' })
  ),
  Check: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2.5, ...props },
    React.createElement('path', { d: 'M5 13l4 4L19 7', strokeLinecap: 'round', strokeLinejoin: 'round' })
  ),
  Instagram: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, ...props },
    React.createElement('rect', { x: 3, y: 3, width: 18, height: 18, rx: 5 }),
    React.createElement('circle', { cx: 12, cy: 12, r: 4 }),
    React.createElement('circle', { cx: 17.5, cy: 6.5, r: 1, fill: 'currentColor' })
  ),
  Facebook: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'currentColor', ...props },
    React.createElement('path', { d: 'M14 9h3V5h-3c-2.2 0-4 1.8-4 4v2H7v4h3v8h4v-8h3l1-4h-4V9c0-.6.4-1 1-1z' })
  ),
  User: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, ...props },
    React.createElement('circle', { cx: 12, cy: 8, r: 4 }),
    React.createElement('path', { d: 'M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8', strokeLinecap: 'round' })
  ),
  Chevron: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.8, ...props },
    React.createElement('path', { d: 'M6 9l6 6 6-6', strokeLinecap: 'round', strokeLinejoin: 'round' })
  ),
  Calendar: (props) => React.createElement('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, ...props },
    React.createElement('rect', { x: 3, y: 5, width: 18, height: 16, rx: 2 }),
    React.createElement('path', { d: 'M3 10h18M8 3v4M16 3v4', strokeLinecap: 'round' })
  )
};
window.Icon = Icon;
