// Main app — Saladin Numerology multi-screen prototype
// Screens: landing → form → result. Switch via Tweaks panel or in-page buttons.

const { useState, useEffect, useRef, useCallback } = React;

function readProfileFromUrl() {
  if (typeof window === 'undefined') return {};
  const p = new URLSearchParams(window.location.search || '');
  const name = (p.get('name') || '').trim();
  const dob = (p.get('dob') || '').trim();
  const gender = (p.get('gender') || '').trim();
  const out = {};
  if (name) out.name = name;
  if (dob) out.dob = dob;
  if (gender) out.gender = gender;
  return out;
}

function profileToSearch(profile) {
  const p = new URLSearchParams();
  if (profile && profile.name) p.set('name', profile.name);
  if (profile && profile.dob) p.set('dob', profile.dob);
  if (profile && profile.gender) p.set('gender', profile.gender);
  const s = p.toString();
  return s ? `?${s}` : '';
}

function screenFromPath(pathname) {
  const path = (pathname || '/').replace(/\/+$/, '') || '/';
  if (path === '/' || path === '/home') return 'landing';
  if (path === '/form') return 'form';
  if (path === '/result') return 'result';
  if (path === '/detail') return 'detail';
  if (path === '/poster') return 'poster';
  return 'landing';
}

function pathFromScreen(screen) {
  if (screen === 'form') return '/form';
  if (screen === 'result') return '/result';
  if (screen === 'detail') return '/detail';
  if (screen === 'poster') return '/poster';
  return '/';
}

// Default tweak values — host parses this JSON and rewrites on edits
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "viewport": "desktop",
  "dark": false,
  "screen": "landing"
}/*EDITMODE-END*/;
// ─────────────────────────────────────────────────────────────
// Reveal-on-scroll using IntersectionObserver
// ─────────────────────────────────────────────────────────────
function useReveal(deps = []) {
  useEffect(() => {
    const root = document.querySelector('.page-root');
    if (!root) return;
    const sections = root.querySelectorAll('[data-reveal]');
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add('is-visible');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -60px 0px' });
    sections.forEach(s => io.observe(s));
    return () => io.disconnect();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, deps);
}

// ─────────────────────────────────────────────────────────────
// Landing — wraps the marketing page sections
// ─────────────────────────────────────────────────────────────
function LandingPage({ mobile, onNavigate, initialData, onDraftChange }) {
  useReveal([mobile]);
  return (
    <div className="page-root" data-screen-label="01 Landing" data-mobile={mobile ? '1' : '0'} style={{
      width: '100%', minHeight: '100%',
      background: 'var(--bg)', color: 'var(--text-default)',
      fontFamily: 'var(--font-sans)', overflowX: 'hidden',
    }}>
      <NumHeader mobile={mobile} />
      <NumHero
        mobile={mobile}
        initialData={initialData}
        onDraftChange={onDraftChange}
        onCta={(payload) => onNavigate('form', payload)}
      />
      <NumWhat mobile={mobile} />
      <NumHow mobile={mobile} />
      <NumTestimonials mobile={mobile} />
      <NumCrossSell mobile={mobile} />
      <NumFooter mobile={mobile} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Form wrapper page (with header + footer)
// ─────────────────────────────────────────────────────────────
function FormPage({ mobile, onSubmit, onBack, initialData, onDraftChange }) {
  return (
    <div className="page-root" data-screen-label="02 Form" data-mobile={mobile ? '1' : '0'} style={{
      width: '100%', minHeight: '100%',
      background: 'var(--bg)', color: 'var(--text-default)',
      fontFamily: 'var(--font-sans)', overflowX: 'hidden',
    }}>
      <NumHeader mobile={mobile} />
      <FormScreen mobile={mobile} onSubmit={onSubmit} onBack={onBack} initialData={initialData} onDraftChange={onDraftChange} />
      <NumFooter mobile={mobile} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Result wrapper page
// ─────────────────────────────────────────────────────────────
function ResultPage({ mobile, user, onBack, onShare, onOpenDetail, onOpenPoster }) {
  return (
    <div className="page-root" data-screen-label="03 Result" data-mobile={mobile ? '1' : '0'} style={{
      width: '100%', minHeight: '100%',
      background: 'var(--bg)', color: 'var(--text-default)',
      fontFamily: 'var(--font-sans)', overflowX: 'hidden',
    }}>
      <NumHeader mobile={mobile} />
      <ResultScreen mobile={mobile} user={user} onBack={onBack} onShare={onShare} onOpenDetail={onOpenDetail} onOpenPoster={onOpenPoster} />
      <NumFooter mobile={mobile} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Detail wrapper page
// ─────────────────────────────────────────────────────────────
function DetailPage({ mobile, n, user, onBack, onShare }) {
  return (
    <div className="page-root" data-screen-label="04 Detail" data-mobile={mobile ? '1' : '0'} style={{
      width: '100%', minHeight: '100%',
      background: 'var(--bg)', color: 'var(--text-default)',
      fontFamily: 'var(--font-sans)', overflowX: 'hidden',
    }}>
      <NumHeader mobile={mobile} />
      <DetailScreen mobile={mobile} n={n} user={user} onBack={onBack} onShare={onShare} />
      <NumFooter mobile={mobile} />
    </div>
  );
}


// ─────────────────────────────────────────────────────────────
// Poster wrapper page
// ─────────────────────────────────────────────────────────────
function PosterPage({ mobile, user, onBack }) {
  return (
    <div className="page-root" data-screen-label="05 Poster" data-mobile={mobile ? '1' : '0'} style={{
      width: '100%', minHeight: '100%',
      background: 'var(--bg)', color: 'var(--text-default)',
      fontFamily: 'var(--font-sans)', overflowX: 'hidden',
    }}>
      <NumHeader mobile={mobile} />
      <PosterScreen mobile={mobile} user={user} onBack={onBack} />
      <NumFooter mobile={mobile} />
    </div>
  );
}
// ─────────────────────────────────────────────────────────────
// Mobile frame — iPhone-ish shell, scrollable inside
// ─────────────────────────────────────────────────────────────
function MobileFrame({ children, dark, scrollKey }) {
  const ref = useRef(null);
  useEffect(() => { if (ref.current) ref.current.scrollTop = 0; }, [scrollKey]);
  const vh = typeof window !== 'undefined' ? window.innerHeight : 844;
  const shellHeight = Math.min(844, Math.max(680, vh - 24));
  return (
    <div style={{
      display: 'flex', justifyContent: 'center', alignItems: 'flex-start',
      padding: '12px 8px 24px',
      minHeight: '100dvh',
      background: dark ? '#0A0F0B' : '#E5EBE8',
      transition: 'background 250ms',
    }}>
      <div style={{
        width: 'min(100vw - 16px, 390px)',
        height: shellHeight,
        maxHeight: 'calc(100dvh - 24px)',
        background: 'var(--bg)',
        borderRadius: 28,
        border: dark ? '1px solid rgba(255,255,255,0.08)' : '1px solid #DCDFE3',
        boxShadow: '0 24px 48px -12px rgba(16,24,40,0.18), 0 8px 16px -4px rgba(16,24,40,0.06)',
        overflow: 'hidden',
        position: 'relative',
        display: 'flex', flexDirection: 'column',
      }}>
        {/* Status bar */}
        <div style={{
          height: 44, flexShrink: 0,
          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
          padding: '0 28px',
          background: 'var(--bg)',
          color: 'var(--text-default)',
          fontSize: 14, fontWeight: 600,
          fontFamily: 'var(--font-ios)',
          position: 'relative', zIndex: 60,
        }}>
          <span>9:41</span>
          <div style={{
            position: 'absolute', left: '50%', top: 10, transform: 'translateX(-50%)',
            width: 110, height: 32, borderRadius: 20, background: '#000',
          }}/>
          <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
            <i className="ri-signal-tower-line" style={{ fontSize: 13 }}></i>
            <i className="ri-wifi-line" style={{ fontSize: 13 }}></i>
            <i className="ri-battery-2-line" style={{ fontSize: 14 }}></i>
          </div>
        </div>
        <div ref={ref} style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch' }}>
          {children}
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Desktop frame — browser-like chrome around 1440 viewport
// ─────────────────────────────────────────────────────────────
function DesktopFrame({ children }) {
  // Production layout — no fake browser chrome, render full bleed.
  return (
    <div style={{
      background: 'var(--bg)',
      minHeight: '100vh',
      boxSizing: 'border-box',
    }}>
      {children}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// App shell with tweaks + router state
// ─────────────────────────────────────────────────────────────
function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const urlProfile = readProfileFromUrl();
  const [user, setUser] = useState(() => {
    try {
      const raw = sessionStorage.getItem('saladin-than-so-current');
      const parsed = raw ? JSON.parse(raw) : null;
      const merged = { ...(parsed || {}), ...urlProfile };
      if (parsed && urlProfile && (urlProfile.name || urlProfile.dob || urlProfile.gender)) {
        const changed =
          (urlProfile.name && urlProfile.name !== parsed.name) ||
          (urlProfile.dob && urlProfile.dob !== parsed.dob) ||
          (urlProfile.gender && urlProfile.gender !== parsed.gender);
        if (changed && merged.numbers) delete merged.numbers;
      }
      return (merged && merged.name && merged.dob) ? merged : (parsed || null);
    } catch (e) { return (urlProfile.name && urlProfile.dob) ? urlProfile : null; }
  });
  const [detailN, setDetailN] = useState(7);
  const [shareOpen, setShareOpen] = useState(false);
  const [formDraft, setFormDraft] = useState(() => {
    try {
      const raw = sessionStorage.getItem('saladin-than-so-draft');
      const parsed = raw ? JSON.parse(raw) : {};
      return { ...parsed, ...urlProfile };
    } catch (e) { return { ...urlProfile }; }
  });

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', t.dark ? 'dark' : 'light');
  }, [t.dark]);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const parsePath = () => {
      const next = screenFromPath(window.location.pathname);
      setTweak('screen', next);
    };
    parsePath();
    window.addEventListener('popstate', parsePath);
    return () => window.removeEventListener('popstate', parsePath);
  }, []);

  const autoMobile = typeof window !== 'undefined' && window.innerWidth <= 768;
  const mobile = t.viewport === 'mobile' || autoMobile;
  const screen = t.screen || 'landing';

  useEffect(() => {
    if (typeof window === 'undefined') return;
    const profile = { ...(formDraft || {}), ...(user || {}) };
    const desired = profileToSearch(profile);
    const current = window.location.search || '';
    if (desired !== current) {
      history.replaceState(null, '', `${window.location.pathname}${desired}`);
    }
  }, [formDraft, user]);

  const upsertDraft = useCallback((patch) => {
    setFormDraft((prev) => {
      const next = { ...prev, ...patch };
      const same = JSON.stringify(prev) === JSON.stringify(next);
      if (!same) {
        try { sessionStorage.setItem('saladin-than-so-draft', JSON.stringify(next)); } catch (e) {}
      }
      return same ? prev : next;
    });
  }, []);

  const navigate = (next, payload) => {
    if (next === 'form' && payload) {
      upsertDraft(payload);
    }
    if (next === 'result' && payload) {
      setUser(payload);
    } else if (next === 'result' && !payload && typeof window !== 'undefined') {
      try {
        const raw = sessionStorage.getItem('saladin-than-so-current');
        const cached = raw ? JSON.parse(raw) : null;
        if (cached && cached.name && cached.dob) {
          if (!cached.numbers && window.SaladinNumerology && window.SaladinNumerology.calculateAll) {
            cached.numbers = window.SaladinNumerology.calculateAll({ name: cached.name, dob: cached.dob });
          }
          setUser(cached);
        }
      } catch (e) {}
    }
    if (next === 'detail' && payload && payload.n) setDetailN(payload.n);
    setTweak('screen', next);
    if (typeof window !== 'undefined') {
      const targetPath = pathFromScreen(next);
      const url = `${targetPath}${window.location.search || ''}`;
      if (window.location.pathname !== targetPath) history.pushState(null, '', url);
    }
    setShareOpen(false);
  };

  useEffect(() => {
    if (!user && (screen === 'result' || screen === 'detail' || screen === 'poster')) {
      setTweak('screen', 'form');
      if (typeof window !== 'undefined' && window.location.pathname !== '/form') {
        history.replaceState(null, '', `/form${window.location.search || ''}`);
      }
    }
  }, [screen, user]);

  const openShare = () => setShareOpen(true);
  const openDetail = (n) => navigate('detail', { n });
  const Content = (typeof window !== 'undefined' && window.SaladinContent) || {};
  const N = (typeof window !== 'undefined' && window.SaladinNumerology) || {};
  const detailNumberOptions = Object.keys((Content && Content.NUMBER_CONTENT) || {})
    .map(Number)
    .filter((v) => Number.isFinite(v))
    .sort((a, b) => a - b)
    .map((n) => ({ value: String(n), label: `Life Path ${n} — ${(N.NUMBER_NAMES && N.NUMBER_NAMES[n]) || 'Chi tiết'}` }));

  const u = user || { name: 'Bạn', dob: '1990-01-01' };

  const body = (() => {
    if (screen === 'form') {
      return <FormPage mobile={mobile}
                       onBack={() => navigate('landing')}
                       initialData={formDraft}
                       onDraftChange={upsertDraft}
                       onSubmit={(data) => {
                         const N = window.SaladinNumerology;
                         const numbers = N && N.calculateAll ? N.calculateAll(data) : {};
                         if (N && N.trackEvent) N.trackEvent('form_submitted', {
                           gender: data.gender || 'skip',
                           has_email: !!data.email,
                         });
                         upsertDraft(data);
                         try { sessionStorage.setItem('saladin-than-so-current', JSON.stringify({ ...data, numbers })); } catch(e) {}
                         navigate('result', { ...data, numbers });
                       }} />;
    }
    if (screen === 'result') {
      return <ResultPage mobile={mobile}
                         user={u}
                         onBack={() => navigate('landing')}
                         onShare={openShare}
                         onOpenDetail={openDetail}
                         onOpenPoster={openShare} />;
    }
    if (screen === 'poster') {
      return <PosterPage mobile={mobile}
                         user={u}
                         onBack={() => navigate('result')} />;
    }
    if (screen === 'detail') {
      return <DetailPage mobile={mobile} n={detailN}
                         user={u}
                         onBack={() => navigate('result')}
                         onShare={openShare} />;
    }
    return <LandingPage
      mobile={mobile}
      onNavigate={navigate}
      initialData={formDraft}
      onDraftChange={upsertDraft}
    />;
  })();

  return (
    <>
      <div style={{ position: 'relative' }}>
        {mobile ? (
          <MobileFrame dark={t.dark} scrollKey={screen + ':' + detailN}>{body}</MobileFrame>
        ) : (
          <DesktopFrame>{body}</DesktopFrame>
        )}
        {/* Share modal is rendered relative to the frame container */}
        <ShareModal open={shareOpen} onClose={() => setShareOpen(false)} user={u} n={detailN} />
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Screen">
          <TweakSelect
            label="Page"
            value={screen}
            onChange={(v) => navigate(v)}
            options={[
              { value: 'landing', label: '01 — Landing' },
              { value: 'form',    label: '02 — Form' },
              { value: 'result',  label: '03 — Result' },
              { value: 'detail',  label: '04 — Detail (1 con số)' },
              { value: 'poster',  label: '05 — Poster Generator' },
            ]}
          />
          {screen === 'detail' && (
            <TweakSelect
              label="Số"
              value={String(detailN)}
              onChange={(v) => setDetailN(Number(v))}
              options={detailNumberOptions.length ? detailNumberOptions : [{ value: '7', label: 'Life Path 7 — Chi tiết' }]}
            />
          )}
          <TweakButton label="Mở Share modal" onClick={openShare} />
        </TweakSection>

        <TweakSection label="Viewport">
          <TweakRadio
            label="Form factor"
            value={t.viewport}
            onChange={(v) => setTweak('viewport', v)}
            options={[
              { value: 'desktop', label: 'Desktop' },
              { value: 'mobile', label: 'Mobile' },
            ]}
          />
        </TweakSection>

        <TweakSection label="Theme">
          <TweakToggle
            label="Dark mode"
            value={t.dark}
            onChange={(v) => setTweak('dark', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

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