// ArtisanFlow — Root App

function ArtisanApp({ showPrototypeShell = false } = {}) {
  // ─── Tweak-persisted state ───
  const TWEAKS = /*EDITMODE-BEGIN*/{
    "dark": false,
    "userName": "Thomas Durand",
    "offline": false,
    "currency": "EUR"
  }/*EDITMODE-END*/;

  const [dark, setDark] = React.useState(TWEAKS.dark);
  const [userName, setUserName] = React.useState(TWEAKS.userName);
  const [offline, setOffline] = React.useState(TWEAKS.offline);
  const [networkOnline, setNetworkOnline] = React.useState(() => (typeof navigator !== 'undefined' ? navigator.onLine : true));
  const [currency, setCurrency] = React.useState(TWEAKS.currency);
  const [rgpdConsent, setRgpdConsent] = React.useState(() => localStorage.getItem('rgpd_consent') === 'true');

  React.useEffect(() => {
    const on = () => setNetworkOnline(true);
    const off = () => setNetworkOnline(false);
    window.addEventListener('online', on);
    window.addEventListener('offline', off);
    return () => {
      window.removeEventListener('online', on);
      window.removeEventListener('offline', off);
    };
  }, []);

  // ─── Edit-mode protocol ───
  React.useEffect(() => {
    const handle = (e) => {
      if (!e.data || typeof e.data !== 'object') return;
      if (e.data.type === '__activate_edit_mode') setTweaksOpen(true);
      if (e.data.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', handle);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handle);
  }, []);

  const [tweaksOpen, setTweaksOpen] = React.useState(false);

  const setTweak = (key, value) => {
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [key]: value } }, '*');
  };

  const t = useAfTheme(dark);

  const [isNarrow, setIsNarrow] = React.useState(
    () => typeof window !== 'undefined' && window.matchMedia('(max-width: 768px)').matches
  );
  React.useEffect(() => {
    const mq = window.matchMedia('(max-width: 768px)');
    const fn = () => setIsNarrow(mq.matches);
    if (mq.addEventListener) mq.addEventListener('change', fn);
    else mq.addListener(fn);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', fn);
      else mq.removeListener(fn);
    };
  }, []);

  // ─── Mobile navigation ───
  const [mobileView, setMobileView] = React.useState('dashboard');
  const [detailQuoteId, setDetailQuoteId] = React.useState(null);
  const [history, setHistory] = React.useState(['dashboard']);

  const setView = (v, id) => {
    if (v === 'signature' && id && typeof AF_STORE !== 'undefined' && AF_STORE.isDevisReadOnlyById(id)) {
      if (id) setDetailQuoteId(id);
      setHistory((h) => [...h, 'detail']);
      setMobileView('detail');
      return;
    }
    if (v === 'detail' || v === 'signature') {
      if (id) setDetailQuoteId(id);
      setHistory((h) => [...h, v]);
      setMobileView(v);
    } else {
      setHistory([v]);
      setMobileView(v);
    }
  };
  const goBack = () => {
    if (history.length <= 1) {
      setMobileView('dashboard');
      setHistory(['dashboard']);
      return;
    }
    const next = history.slice(0, -1);
    setHistory(next);
    setMobileView(next[next.length - 1]);
  };

  const renderMobile = () => {
    if (mobileView === 'dashboard') return <AfDashboard t={t} currency={currency} userName={userName} onNewNote={() => setView('note-flash')} setView={setView} onOpenSettings={() => setView('profile')} networkOnline={networkOnline}/>;
    if (mobileView === 'notes') return <AfPaiements t={t} currency={currency} setView={setView}/>;
    if (mobileView === 'clients') return <AfClientsList t={t} currency={currency} setView={setView}/>;
    if (mobileView === 'paiements') return <AfPaiements t={t} currency={currency} setView={setView}/>;
    if (mobileView === 'note-flash') return <AfNoteFlash t={t} currency={currency} onBack={goBack} onSave={(data) => { goBack(); }} setView={setView}/>;
    if (mobileView === 'detail') return <AfQuoteDetail t={t} currency={currency} quoteId={detailQuoteId} onBack={goBack} setView={setView}/>;
    if (mobileView === 'profile') return <AfProfile t={t} onBack={goBack}/>;
    if (mobileView === 'settings') return <AfSettings t={t} onBack={goBack} userName={userName} setUserName={setUserName} dark={dark} setDark={setDark} currency={currency} setCurrency={setCurrency} offline={offline} setOffline={setOffline}/>;
    if (mobileView === 'catalogue') return <AfCatalogue t={t} onBack={goBack}/>;
    if (mobileView === 'signature') return <AfSignature t={t} devisId={detailQuoteId} clientName={AF_STORE.getDevisById(detailQuoteId)?.clientName} onSave={(sig) => { goBack(); }} onCancel={goBack}/>;
    return null;
  };

  // Bottom nav should only show on main tabs, not modals/detail
  // Barre : Accueil, Devis, Clients uniquement (plus d’onglet « Paiements » dupliqué — même écran que Devis)
  const showBottomNav = ['dashboard', 'notes', 'clients'].includes(mobileView);

  const mobileInner = (
    <div style={{
      flex: 1, display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0,
      paddingBottom: isNarrow ? 'env(safe-area-inset-bottom, 0px)' : undefined,
    }}>
      <div style={{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
        {renderMobile()}
      </div>
      {showBottomNav && (
        <AfBottomNav active={mobileView} onChange={setMobileView} t={t}/>
      )}
    </div>
  );

  const shellBg = dark
    ? 'radial-gradient(circle at 20% 10%, rgba(58,168,232,0.06), transparent 50%), radial-gradient(circle at 80% 80%, rgba(255,138,61,0.04), transparent 50%)'
    : 'radial-gradient(circle at 20% 10%, rgba(11,61,92,0.04), transparent 50%), radial-gradient(circle at 80% 80%, rgba(255,107,0,0.03), transparent 50%)';

  if (!showPrototypeShell) {
    return (
      <>
        <style dangerouslySetInnerHTML={{ __html: AF_FONTS }}/>
        <div className="af-app" style={{
          minHeight: '100dvh', width: '100%',
          background: dark ? '#0A0F18' : '#DAD5CC',
          display: 'flex', flexDirection: 'column',
          backgroundImage: shellBg,
          color: t.text,
        }}>
          {isNarrow ? (
            <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
              {mobileInner}
            </div>
          ) : (
            <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
              <AfWebView t={t} currency={currency} userName={userName} dark={dark} offline={offline} networkOnline={networkOnline}/>
            </div>
          )}
        </div>
      </>
    );
  }

  return (
    <>
      <style dangerouslySetInnerHTML={{ __html: AF_FONTS }}/>
      <div className="af-app" style={isNarrow ? {
        minHeight: '100dvh', width: '100%', maxWidth: '100vw',
        background: dark ? '#0A0F18' : '#DAD5CC',
        display: 'flex', flexDirection: 'column', alignItems: 'stretch',
        padding: 0, margin: 0,
        overflow: 'hidden', overflowX: 'hidden',
        boxSizing: 'border-box',
        flex: 1,
        backgroundImage: shellBg,
        color: t.text,
      } : {
        minHeight: '100vh', width: '100%',
        background: dark ? '#0A0F18' : '#DAD5CC',
        display: 'flex', flexDirection: 'column', alignItems: 'center',
        padding: '40px 24px 60px',
        backgroundImage: shellBg,
        color: t.text,
      }}>
        {!isNarrow && (
          <>
            <div style={{ maxWidth: 1400, width: '100%', marginBottom: 20 }}>
              <IdLogoWordmark t={t} size="lg" showTag tag="Prototype · v0.1"/>
              <div style={{
                marginTop: 10,
                fontSize: 16, fontWeight: 700, color: t.safety,
                letterSpacing: -0.3, fontStyle: 'italic',
              }}>
                « Le devis pro, à la voix, instantanément. »
              </div>
              <div style={{ fontSize: 14, color: t.textMuted, fontWeight: 500, maxWidth: 720, marginTop: 8 }}>
                Gestion de devis & notes de terrain pour artisans du bâtiment. Pensé pour le chantier : gros doigts, haute visibilité, hors-ligne.
                <span style={{ marginLeft: 8, fontSize: 12, opacity: 0.7 }}>
                  Mobile ↔ Web · multi-métiers · dictée vocale
                </span>
              </div>
            </div>

            <div style={{
              maxWidth: 1400, width: '100%',
              display: 'grid', gridTemplateColumns: '410px 1fr', gap: 32,
              alignItems: 'start',
            }}>
              <div>
                <AfColumnLabel t={t} num="MOBILE" label="Terrain / chantier"/>
                <AfPhoneFrame t={t} dark={dark} offline={offline} networkOnline={networkOnline} currency={currency} fullBleed={false}>
                  {mobileInner}
                </AfPhoneFrame>

                <div style={{ marginTop: 16, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                  {[
                    { id: 'dashboard', label: 'Tableau' },
                    { id: 'note-flash', label: '⚡ Instant Note' },
                    { id: 'catalogue', label: 'Catalogue' },
                    { id: 'clients', label: 'Clients' },
                    { id: 'detail', label: 'Détail devis', extra: 'Q-2026-041' },
                    { id: 'profile', label: 'Profil Pro' },
                    { id: 'settings', label: 'Paramètres' },
                  ].map(s => (
                    <button key={s.id} onClick={() => setView(s.id, s.extra)} style={{
                      padding: '6px 10px', borderRadius: 4,
                      background: mobileView === s.id ? t.primary : t.bgElevated,
                      color: mobileView === s.id ? '#fff' : t.text,
                      border: `1px solid ${mobileView === s.id ? t.primary : t.border}`,
                      fontSize: 11, fontWeight: 700,
                    }}>
                      {s.label}
                    </button>
                  ))}
                </div>
              </div>

              <div>
                <AfColumnLabel t={t} num="WEB" label="Bureau · suivi devis & clients"/>
                <div style={{
                  border: `1px solid ${t.borderStrong}`, borderRadius: 10,
                  overflow: 'hidden',
                  boxShadow: '0 30px 60px rgba(0,0,0,0.18)',
                  height: 820,
                }}>
                  <div style={{
                    height: 38, background: dark ? '#1A2331' : '#E7E4DE',
                    borderBottom: `1px solid ${t.border}`,
                    display: 'flex', alignItems: 'center', padding: '0 12px', gap: 6,
                  }}>
                    <div style={{ display: 'flex', gap: 6 }}>
                      <div style={{ width: 11, height: 11, borderRadius: '50%', background: '#FF5F57' }}/>
                      <div style={{ width: 11, height: 11, borderRadius: '50%', background: '#FEBC2E' }}/>
                      <div style={{ width: 11, height: 11, borderRadius: '50%', background: '#28C840' }}/>
                    </div>
                    <div style={{
                      flex: 1, marginLeft: 16, maxWidth: 400,
                      height: 24, background: dark ? '#0D1520' : '#F1EFEB',
                      borderRadius: 4, display: 'flex', alignItems: 'center', gap: 8,
                      padding: '0 10px', fontSize: 11, color: t.textMuted, fontWeight: 600,
                    }}>
                      <lucide.Lock size={10}/>
                      app.instantdevis.fr/devis
                    </div>
                    <div style={{ flex: 1 }}/>
                  </div>
                  <div style={{ height: 'calc(100% - 38px)' }}>
                    <AfWebView t={t} currency={currency} userName={userName} dark={dark} offline={offline} networkOnline={networkOnline}/>
                  </div>
                </div>
              </div>
            </div>
          </>
        )}

        {isNarrow && (
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, minWidth: 0, width: '100%' }}>
            <AfPhoneFrame t={t} dark={dark} offline={offline} networkOnline={networkOnline} currency={currency} fullBleed>
              {mobileInner}
            </AfPhoneFrame>
          </div>
        )}

        {/* Tweaks panel */}
        {tweaksOpen && (
          <AfTweaksPanel
            t={t}
            dark={dark} setDark={(v) => { setDark(v); setTweak('dark', v); }}
            userName={userName} setUserName={(v) => { setUserName(v); setTweak('userName', v); }}
            offline={offline} setOffline={(v) => { setOffline(v); setTweak('offline', v); }}
            currency={currency} setCurrency={(v) => { setCurrency(v); setTweak('currency', v); }}
            onClose={() => setTweaksOpen(false)}
          />
        )}

        {/* RGPD Consent Banner */}
        {!rgpdConsent && (
          <div style={{
            position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 9999,
            background: t.bgElevated, borderTop: `2px solid ${t.safety}`,
            padding: '20px 24px calc(20px + env(safe-area-inset-bottom, 0px))', boxShadow: '0 -10px 40px rgba(0,0,0,0.2)',
            display: 'flex', flexDirection: 'column', gap: 14,
            animation: 'af-slide-up 0.5s both',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <lucide.Shield size={24} color={t.safety} />
              <div style={{ fontSize: 16, fontWeight: 800, color: t.text }}>Vos données sont à vous.</div>
            </div>
            <div style={{ fontSize: 13, color: t.textMuted, lineHeight: 1.5 }}>
              Cette application conserve vos devis, catalogue et profil <strong>localement</strong> sur votre appareil (localStorage) tant que vous n’utilisez pas de synchronisation cloud. Les transcriptions avancées et l’envoi d’e-mails passent par un <strong>Cloudflare Worker</strong> que vous déployez vous-même (aucune clé secrète n’est requise dans l’appli).
            </div>
            <button onClick={() => {
              localStorage.setItem('rgpd_consent', 'true');
              setRgpdConsent(true);
            }} style={{
              width: '100%', padding: '12px', borderRadius: 8,
              background: t.safety, color: '#fff', border: 'none',
              fontSize: 14, fontWeight: 800, cursor: 'pointer',
            }}>
              J'ai compris et j'accepte
            </button>
          </div>
        )}
      </div>
    </>
  );
}

function AfColumnLabel({ t, num, label }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16 }}>
      <span className="af-mono" style={{
        fontSize: 10, padding: '3px 7px', borderRadius: 3,
        background: t.safety, color: '#0D1520',
        fontWeight: 800, letterSpacing: 0.8,
      }}>{num}</span>
      <span style={{
        fontSize: 12, fontWeight: 800, color: t.textMuted,
        letterSpacing: 1.2, textTransform: 'uppercase',
      }}>{label}</span>
      <div style={{ flex: 1, height: 1, background: t.border }}/>
    </div>
  );
}

function AfTweaksPanel({ t, dark, setDark, userName, setUserName, offline, setOffline, currency, setCurrency, onClose }) {
  return (
    <div style={{
      position: 'fixed', bottom: 20, right: 20, zIndex: 200,
      width: 320, background: t.bgElevated,
      border: `1px solid ${t.borderStrong}`, borderRadius: 10,
      boxShadow: '0 24px 48px rgba(0,0,0,0.3)',
      overflow: 'hidden',
    }}>
      <div style={{
        padding: '12px 14px', background: t.primary, color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        position: 'relative', overflow: 'hidden',
      }}>
        <div className="af-hazard" style={{
          position: 'absolute', inset: 0, width: '100%', color: t.safety, opacity: 0.12,
        }}/>
        <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 8 }}>
          <lucide.Settings2 size={16} strokeWidth={2.6}/>
          <span style={{ fontSize: 13, fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase' }}>
            Tweaks
          </span>
        </div>
        <button onClick={onClose} style={{ position: 'relative', color: '#fff', padding: 4 }}>
          <lucide.X size={16} strokeWidth={2.6}/>
        </button>
      </div>
      <div style={{ padding: '14px' }}>
        <AfTweakRow label="Mode sombre">
          <AfSwitch value={dark} onChange={setDark} t={t} label="Activer le mode sombre"/>
        </AfTweakRow>
        <AfTweakRow label="Hors-ligne">
          <AfSwitch value={offline} onChange={setOffline} t={t} accent={t.safety} label="Simuler le mode hors-ligne"/>
        </AfTweakRow>
        <AfTweakRow label="Devise">
          <div style={{ display: 'flex', gap: 4 }}>
            {['EUR', 'CHF'].map(c => (
              <button key={c} onClick={() => setCurrency(c)} style={{
                padding: '5px 10px', borderRadius: 4, fontSize: 11, fontWeight: 700,
                background: currency === c ? t.primary : t.bgSunken,
                color: currency === c ? '#fff' : t.text,
                border: `1px solid ${currency === c ? t.primary : t.border}`,
              }}>{c}</button>
            ))}
          </div>
        </AfTweakRow>
        <AfTweakRow label="Nom artisan" full>
          <input
            value={userName} onChange={e => setUserName(e.target.value)}
            style={{
              width: '100%', padding: '7px 10px', borderRadius: 4,
              background: t.bgSunken, border: `1px solid ${t.border}`,
              fontSize: 12, fontWeight: 600, color: t.text,
            }}
          />
        </AfTweakRow>
      </div>
    </div>
  );
}

function AfTweakRow({ label, children, full }) {
  return (
    <div style={{
      display: 'flex', alignItems: full ? 'flex-start' : 'center',
      flexDirection: full ? 'column' : 'row',
      gap: full ? 6 : 10,
      padding: '8px 0', borderBottom: '1px solid rgba(128,128,128,0.1)',
    }}>
      <span style={{
        fontSize: 11, fontWeight: 700, letterSpacing: 0.5, textTransform: 'uppercase',
        opacity: 0.7, flex: full ? 'none' : 1,
      }}>{label}</span>
      {children}
    </div>
  );
}

function AfSwitch({ value, onChange, t, accent, label }) {
  const toggle = () => onChange(!value);
  return (
    <div
      onClick={toggle}
      onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } }}
      role="switch"
      aria-checked={value}
      aria-label={label}
      tabIndex={0}
      style={{
        width: 36, height: 20, borderRadius: 10, cursor: 'pointer',
        background: value ? (accent || t.primary) : t.bgSunken,
        position: 'relative', transition: 'background 0.2s',
        border: `1px solid ${value ? 'transparent' : t.border}`,
        outline: 'none',
      }}>
      <div style={{
        position: 'absolute', top: 1, left: value ? 16 : 1,
        width: 16, height: 16, borderRadius: '50%', background: '#fff',
        transition: 'left 0.2s cubic-bezier(0.2, 0.8, 0.2, 1)',
        boxShadow: '0 1px 2px rgba(0,0,0,0.3)',
      }}/>
    </div>
  );
}

function AfRoot() {
  const pathname = String(window.location.pathname || '');

  if (pathname.startsWith('/signature/')) {
    const PublicSignaturePage = window.SignaturePage;
    return PublicSignaturePage
      ? <PublicSignaturePage />
      : <div style={{ padding: 24 }}>Chargement du module de signature impossible. Veuillez réessayer.</div>;
  }

  if (pathname === '/' || pathname === '') {
    const PublicLandingPage = window.LandingPage;
    return PublicLandingPage
      ? <PublicLandingPage />
      : <div style={{ padding: 24 }}>Chargement de la page InstantDevis...</div>;
  }

  if (pathname === '/app' || pathname.startsWith('/app/')) {
    return <ArtisanApp showPrototypeShell={false} />;
  }

  if (pathname === '/prototype' || pathname.startsWith('/prototype/')) {
    return <ArtisanApp showPrototypeShell={true} />;
  }

  return <ArtisanApp showPrototypeShell={false} />;
}

Object.assign(window, { AfRoot });

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