// extras.jsx — ErrorBoundary, WhatsAppFab, CookieBanner, PrivacyPage, NotFoundPage

class ErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = { error: null }; }
  static getDerivedStateFromError(error) { return { error }; }
  componentDidCatch(error, info) { console.error('[LESSO app error]', error, info); }
  render() {
    if (this.state.error) {
      return (
        <div style={{ padding: 64, fontFamily: 'ui-sans-serif, system-ui' }}>
          <h1 style={{ fontSize: 28, marginBottom: 12 }}>Something went wrong.</h1>
          <p style={{ color: '#666', marginBottom: 24 }}>Please refresh the page. If the problem persists, contact us.</p>
          <button className="btn btn-primary" onClick={() => { this.setState({ error: null }); location.href = '/'; }}>Go home</button>
          <pre style={{ marginTop: 32, fontSize: 12, color: '#999', whiteSpace: 'pre-wrap' }}>{String(this.state.error?.stack || this.state.error)}</pre>
        </div>
      );
    }
    return this.props.children;
  }
}

// Shared by WhatsAppFab and InquiryDrawer so both surfaces send identical
// pre-filled WhatsApp bodies. If the inquiry list is empty the FAB falls
// back to the generic greeting (LEGAL.whatsapp.msg); only the drawer needs
// the cart-list shape unconditionally.
function buildInquiryWaBody(list, inq) {
  const lines = [
    inq.waGreeting || 'Hi LESSO!',
    '',
    inq.waIntro || 'I would like a quote for the following:',
    '',
    ...list.map((it, idx) => `${idx + 1}. ${it.label}\n   ${it.url}`),
    '',
    inq.waClosing || 'Thanks.',
  ];
  return lines.join('\n');
}

function WhatsAppFab({ lang }) {
  // Number comes from contact.json → window.CONTACT.whatsapp.
  // Generic message + aria come from legal.json → window.LEGAL[lang].whatsapp.
  // When the inquiry-list (window.INQUIRY) has items, the FAB instead sends
  // the same cart-aware body the InquiryDrawer would send — so a user who
  // adds a few products and then taps the FAB (instead of opening the drawer)
  // still gets a pre-filled list, not the generic greeting.
  const rawNumber = (window.CONTACT && window.CONTACT.whatsapp) || '5511930723068';
  // wa.me URLs require digits only — no '+', no spaces, no dashes.
  // Editors routinely type human-readable forms like "+55 11 99999-9999",
  // so strip everything that isn't a digit. If the result is too short
  // to be a real number, hide the FAB rather than render a broken link.
  const number = String(rawNumber).replace(/\D/g, '');

  // Re-render whenever the inquiry list changes so the href stays current.
  const I = (typeof window !== 'undefined') ? window.INQUIRY : null;
  const [list, setList] = useState(() => (I ? I.list : []));
  useEffect(() => {
    if (!I) return;
    const onChange = () => setList([...I.list]);
    window.addEventListener('lesso-inquiry-change', onChange);
    return () => window.removeEventListener('lesso-inquiry-change', onChange);
  }, []);

  if (number.length < 8) return null;

  const wa = (window.LEGAL && window.LEGAL[lang] && window.LEGAL[lang].whatsapp) || {};
  const inq = (window.I18N && window.I18N[lang] && window.I18N[lang].inquiry) || {};
  const FALLBACK_MSG = {
    pt: 'Olá, gostaria de uma cotação da LESSO Brasil.',
    en: 'Hello, I would like a quote from LESSO Brasil.',
    es: 'Hola, quisiera una cotización de LESSO Brasil.',
  };
  const FALLBACK_ARIA = {
    pt: 'Falar no WhatsApp',
    en: 'Chat on WhatsApp',
    es: 'Hablar por WhatsApp',
  };
  const hasList = list.length > 0;
  const msg = hasList
    ? buildInquiryWaBody(list, inq)
    : (wa.msg || FALLBACK_MSG[lang] || FALLBACK_MSG.en);
  const aria = wa.aria || FALLBACK_ARIA[lang] || FALLBACK_ARIA.en;
  const href = `https://wa.me/${number}?text=${encodeURIComponent(msg)}`;
  return (
    <a
      className="wa-fab"
      href={href}
      target="_blank"
      rel="noopener"
      aria-label={aria}
    >
      <svg viewBox="0 0 32 32" width="28" height="28" fill="currentColor" aria-hidden="true">
        <path d="M16 3C9.4 3 4 8.3 4 14.9c0 2.6.8 5 2.3 7L4 29l7.4-2.3c1.9 1 4 1.6 6.2 1.6 6.6 0 12-5.3 12-11.9S22.6 3 16 3zm0 21.6c-1.9 0-3.8-.5-5.4-1.5l-.4-.2-4.4 1.4 1.4-4.3-.3-.4c-1.1-1.7-1.7-3.7-1.7-5.7 0-5.5 4.5-10 10-10s10 4.5 10 10-4.5 10-10 10zm5.5-7.5c-.3-.2-1.8-.9-2.1-1-.3-.1-.5-.2-.7.2-.2.3-.8 1-.9 1.2-.2.2-.3.2-.6.1-.3-.2-1.3-.5-2.5-1.6-.9-.8-1.5-1.8-1.7-2.1-.2-.3 0-.5.1-.6.1-.1.3-.3.4-.5.1-.2.2-.3.3-.5.1-.2 0-.4 0-.5-.1-.2-.7-1.7-1-2.3-.3-.6-.5-.5-.7-.5-.2 0-.4 0-.6 0-.2 0-.5.1-.8.4-.3.3-1 1-1 2.4s1.1 2.8 1.2 3c.2.2 2.1 3.2 5.1 4.5.7.3 1.3.5 1.7.6.7.2 1.4.2 1.9.1.6-.1 1.8-.7 2.1-1.5.3-.7.3-1.3.2-1.5-.1-.2-.3-.2-.6-.3z"/>
      </svg>
      {hasList && <span className="wa-fab__badge" aria-hidden="true">{list.length}</span>}
    </a>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// InquiryDrawer — slide-in panel on the right with the current inquiry list
// and two send CTAs (WhatsApp + email). State exposed globally via
// window.INQUIRY_UI = { openDrawer, closeDrawer } so the Header bag button
// can trigger it without prop-drilling.
// ────────────────────────────────────────────────────────────────────────────
function InquiryDrawer({ t }) {
  const I = (typeof window !== 'undefined') ? window.INQUIRY : null;
  const [open, setOpen] = useState(false);
  const [list, setList] = useState(() => (I ? I.list : []));
  // Re-sync on every change
  useEffect(() => {
    if (!I) return;
    const onChange = () => setList([...I.list]);
    window.addEventListener('lesso-inquiry-change', onChange);
    return () => window.removeEventListener('lesso-inquiry-change', onChange);
  }, []);
  // Expose open/close to the world
  useEffect(() => {
    window.INQUIRY_UI = {
      openDrawer: () => setOpen(true),
      closeDrawer: () => setOpen(false),
    };
    return () => { delete window.INQUIRY_UI; };
  }, []);
  // ESC to close
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open]);
  if (!I) return null;
  const inq = (t && t.inquiry) || {};
  const close = () => setOpen(false);
  const empty = list.length === 0;

  // ── Message builders ─────────────────────────────────────────────────────
  // We render the body templates with the current lang's i18n.inquiry strings.
  // WhatsApp body is shared with WhatsAppFab via buildInquiryWaBody helper
  // above — keep them in sync there, not here.
  const renderWaBody = () => buildInquiryWaBody(list, inq);
  const renderEmailSubject = () => {
    const tpl = inq.emailSubjectTpl || 'Quote request — {n} {productWord}';
    const word = list.length === 1 ? (inq.productWordSingular || 'product') : (inq.productWordPlural || 'products');
    return tpl.replace('{n}', list.length).replace('{productWord}', word);
  };
  const renderEmailBody = () => {
    const lines = [
      inq.emailGreeting || 'Dear LESSO team,',
      '',
      inq.emailIntro || 'I would like a quote for the following:',
      '',
      ...list.map((it, idx) => `${idx + 1}. ${it.label}\n   Link: ${it.url}`),
      '',
      inq.emailRequestDetails || 'Please get in touch to discuss specifications and timelines.',
      '',
      inq.emailSignoff || 'Best regards,',
    ];
    return lines.join('\n');
  };
  const contact = (typeof window !== 'undefined' && window.CONTACT) || {};
  const waDigits = String(contact.whatsapp || '').replace(/[^0-9]/g, '');
  const waUrl = (empty || !waDigits)
    ? '#'
    : 'https://wa.me/' + waDigits + '?text=' + encodeURIComponent(renderWaBody());
  const mailUrl = (empty || !contact.inquiryEmail)
    ? '#'
    : 'mailto:' + contact.inquiryEmail + '?subject=' + encodeURIComponent(renderEmailSubject()) + '&body=' + encodeURIComponent(renderEmailBody());

  return (
    <aside
      className={'inquiry-drawer' + (open ? ' is-open' : '')}
      aria-modal="true"
      role="dialog"
      aria-hidden={!open}
      hidden={!open}
    >
      <div className="inquiry-drawer__backdrop" onClick={close} />
      <div className="inquiry-drawer__panel">
        <header className="inquiry-drawer__header">
          <h2>
            {inq.drawerTitle || 'Inquiry list'}
            {!empty && <span className="inquiry-drawer__count"> ({list.length})</span>}
          </h2>
          <button type="button" className="inquiry-drawer__close" aria-label={inq.drawerClose || 'Close'} onClick={close}>×</button>
        </header>
        {empty ? (
          <div className="inquiry-drawer__empty">
            <p>{inq.emptyTitle || 'Your list is empty.'}</p>
            <p>{inq.emptyHint || ''}</p>
          </div>
        ) : (
          <ul className="inquiry-drawer__items">
            {list.map((it) => (
              <li key={it.key} className="inquiry-drawer__item">
                {it.image
                  ? <img src={it.image} alt="" onError={(e) => { e.currentTarget.style.visibility = 'hidden'; }} />
                  : <div className="inquiry-drawer__placeholder" />}
                <div className="inquiry-drawer__meta">
                  <p className="inquiry-drawer__label">{it.label}</p>
                  <a className="inquiry-drawer__url" href={it.url}>{it.url}</a>
                </div>
                <button
                  type="button"
                  className="inquiry-drawer__remove"
                  aria-label={inq.itemRemove || 'Remove'}
                  onClick={() => I.remove(it.key)}
                >×</button>
              </li>
            ))}
          </ul>
        )}
        <footer className="inquiry-drawer__footer">
          {!empty && (
            <button type="button" className="inquiry-drawer__clear" onClick={() => I.clear()}>
              {inq.clearList || 'Clear'}
            </button>
          )}
          <a
            className={'inquiry-drawer__btn inquiry-drawer__btn--wa' + (empty ? ' is-disabled' : '')}
            href={waUrl}
            target="_blank"
            rel="noopener noreferrer"
            aria-disabled={empty}
            onClick={(e) => { if (empty) e.preventDefault(); }}
          >{inq.sendWhatsApp || 'Send via WhatsApp'}</a>
          <a
            className={'inquiry-drawer__btn inquiry-drawer__btn--email' + (empty ? ' is-disabled' : '')}
            href={mailUrl}
            aria-disabled={empty}
            onClick={(e) => { if (empty) e.preventDefault(); }}
          >{inq.sendEmail || 'Send by email'}</a>
        </footer>
      </div>
    </aside>
  );
}

function CookieBanner({ lang }) {
  const [hidden, setHidden] = useState(() => !!localStorage.getItem('lesso_cookie_ok'));
  if (hidden) return null;
  const fromLegal = window.LEGAL && window.LEGAL[lang] && window.LEGAL[lang].cookie;
  const FALLBACKS = {
    pt: { text: 'Usamos apenas cookies essenciais para o funcionamento do site. Não usamos cookies de rastreamento.', accept: 'Entendi', privacy: 'Política de privacidade' },
    en: { text: 'We only use essential cookies for the site to work. No tracking cookies.', accept: 'Got it', privacy: 'Privacy policy' },
    es: { text: 'Solo utilizamos cookies esenciales para el funcionamiento del sitio. No usamos cookies de rastreo.', accept: 'Entendido', privacy: 'Política de privacidad' },
  };
  const t = fromLegal || FALLBACKS[lang] || FALLBACKS.en;
  const accept = () => { localStorage.setItem('lesso_cookie_ok', '1'); setHidden(true); };
  const privacyUrl = window.buildUrl ? window.buildUrl(lang, 'privacy') : '#';
  return (
    <div className="cookie-banner" role="region" aria-label="Cookie notice">
      <div className="cookie-inner">
        <p>{t.text} <a href={privacyUrl}>{t.privacy}</a></p>
        <button className="btn btn-primary btn-sm" onClick={accept}>{t.accept}</button>
      </div>
    </div>
  );
}

function PrivacyPage({ t, go }) {
  const lang = (t && t.locale) || 'pt';
  const isPt = lang === 'pt';
  const dpoEmail = (window.LEGAL && window.LEGAL.info && window.LEGAL.info.dpoEmail) || 'privacidade@lesso.com';
  const fromLegal = window.LEGAL && window.LEGAL[lang] && window.LEGAL[lang].privacy;
  const PRIVACY_LABEL = { pt: 'Privacidade', en: 'Privacy', es: 'Privacidad' };

  // Render dynamic privacy from window.LEGAL when available; otherwise render
  // the static fallback (preserves original copy if JSON load failed).
  if (fromLegal) {
    // Inline rendering helper: replace {{dpoEmail}} placeholders with a real
    // mailto link element by splitting on the token. Safer than dangerouslySetInnerHTML.
    const renderWithEmail = (text) => {
      const parts = text.split('{{dpoEmail}}');
      return parts.flatMap((part, i) =>
        i < parts.length - 1
          ? [part, <a key={i} href={`mailto:${dpoEmail}`}>{dpoEmail}</a>]
          : [part]
      );
    };
    return (
      <div className="page-enter">
        <section className="page-hero">
          <div className="container">
            <Crumbs items={[{ label: t.nav.home, to: 'home' }, { label: PRIVACY_LABEL[lang] || PRIVACY_LABEL.en }]} go={go} />
            <h1>{fromLegal.pageH1}</h1>
            <p className="lead">{fromLegal.pageLead}</p>
          </div>
        </section>
        <section className="section">
          <div className="container" style={{ maxWidth: 780 }}>
            <div className="privacy-body">
              {(fromLegal.sections || []).map((s, i) => (
                <React.Fragment key={i}>
                  <h3>{s.h}</h3>
                  <p>{renderWithEmail(s.p || '')}</p>
                </React.Fragment>
              ))}
              {fromLegal.lastUpdated && <p className="muted">{fromLegal.lastUpdated}</p>}
            </div>
          </div>
        </section>
      </div>
    );
  }

  // Fallback (LEGAL not loaded) — original static text (PT/EN only;
  // ES users still see PT here if content/legal.json isn't loaded).
  const isEs = lang === 'es';
  const fallbackH1   = { pt: 'Política de Privacidade', en: 'Privacy Policy', es: 'Política de Privacidad' }[lang] || 'Privacy Policy';
  const fallbackLead = {
    pt: 'Como tratamos seus dados ao solicitar uma cotação ou navegar no site.',
    en: 'How we handle your data when you request a quote or browse this site.',
    es: 'Cómo tratamos sus datos al solicitar una cotización o navegar por el sitio.',
  }[lang] || 'How we handle your data when you request a quote or browse this site.';
  return (
    <div className="page-enter">
      <section className="page-hero">
        <div className="container">
          <Crumbs items={[{ label: t.nav.home, to: 'home' }, { label: PRIVACY_LABEL[lang] || PRIVACY_LABEL.en }]} go={go} />
          <h1>{fallbackH1}</h1>
          <p className="lead">{fallbackLead}</p>
        </div>
      </section>
      <section className="section">
        <div className="container" style={{ maxWidth: 780 }}>
          <div className="privacy-body">
            {isEs ? (
              <>
                <h3>1. Datos recopilados</h3>
                <p>Solo recopilamos los datos que nos envía en el formulario de cotización: nombre, empresa, correo electrónico, teléfono, país, sector, línea de producto y detalles técnicos del proyecto.</p>
                <h3>2. Finalidad</h3>
                <p>Los datos se utilizan exclusivamente para responder a su consulta comercial y enviar la documentación técnica relacionada.</p>
                <h3>3. Base legal</h3>
                <p>Tratamos sus datos basándonos en el interés comercial legítimo y en los procedimientos previos al contrato (LGPD Brasil Art. 7º V / IX; GDPR Art. 6(1)(b)/(f) para visitantes de la UE).</p>
                <h3>4. Compartir</h3>
                <p>Sus datos pueden compartirse con el equipo comercial LATAM de LESSO Group. No vendemos ni transferimos datos a terceros con fines de marketing.</p>
                <h3>5. Cookies</h3>
                <p>Solo utilizamos cookies técnicas esenciales (preferencia de idioma y aceptación del aviso de cookies). Sin cookies de rastreo o analítica de terceros.</p>
                <h3>6. Sus derechos</h3>
                <p>Puede solicitar acceso, corrección, anonimización o eliminación de sus datos en cualquier momento: <a href={`mailto:${dpoEmail}`}>{dpoEmail}</a>.</p>
                <h3>7. Retención</h3>
                <p>Los datos de la cotización se conservan hasta 24 meses después del último contacto, salvo que la ley exija un periodo de retención mayor.</p>
                <h3>8. Encargado de protección de datos</h3>
                <p>Correo electrónico: <a href={`mailto:${dpoEmail}`}>{dpoEmail}</a></p>
                <p className="muted">Última actualización: abril de 2026.</p>
              </>
            ) : isPt ? (
              <>
                <h3>1. Dados coletados</h3>
                <p>Coletamos apenas os dados que você nos envia no formulário de cotação: nome, empresa, e-mail, telefone, país, setor, linha de produto e detalhes técnicos do projeto.</p>
                <h3>2. Finalidade</h3>
                <p>Os dados são usados exclusivamente para responder sua solicitação comercial e enviar documentação técnica relacionada.</p>
                <h3>3. Base legal (LGPD)</h3>
                <p>Tratamos seus dados com base no legítimo interesse comercial (Art. 7º, IX da LGPD) e na execução de procedimentos preliminares a contrato (Art. 7º, V).</p>
                <h3>4. Compartilhamento</h3>
                <p>Seus dados podem ser compartilhados com a equipe comercial LATAM da LESSO Group. Não vendemos nem repassamos dados a terceiros para fins de marketing.</p>
                <h3>5. Cookies</h3>
                <p>Usamos apenas cookies técnicos essenciais (preferência de idioma e aceite deste aviso). Não usamos cookies de rastreamento ou analytics de terceiros.</p>
                <h3>6. Seus direitos</h3>
                <p>Você pode solicitar acesso, correção, anonimização ou exclusão dos seus dados a qualquer momento por e-mail: <a href={`mailto:${dpoEmail}`}>{dpoEmail}</a>.</p>
                <h3>7. Retenção</h3>
                <p>Retemos dados de cotação por até 24 meses após o último contato, exceto quando houver obrigação legal de retenção mais longa.</p>
                <h3>8. Contato do encarregado (DPO)</h3>
                <p>E-mail: <a href={`mailto:${dpoEmail}`}>{dpoEmail}</a></p>
                <p className="muted">Última atualização: abril de 2026.</p>
              </>
            ) : (
              <>
                <h3>1. Data we collect</h3>
                <p>We only collect the data you submit in the quote form: name, company, email, phone, country, sector, product line and project technical details.</p>
                <h3>2. Purpose</h3>
                <p>Data is used solely to respond to your commercial inquiry and send related technical documentation.</p>
                <h3>3. Legal basis</h3>
                <p>We process your data based on legitimate commercial interest and pre-contract procedures (Brazil LGPD Art. 7º V / IX; GDPR Art. 6(1)(b)/(f) for EU visitors).</p>
                <h3>4. Sharing</h3>
                <p>Your data may be shared with LESSO Group's LATAM commercial team. We do not sell or transfer data to third parties for marketing.</p>
                <h3>5. Cookies</h3>
                <p>We use only essential technical cookies (language preference and cookie-notice acceptance). No third-party tracking or analytics cookies.</p>
                <h3>6. Your rights</h3>
                <p>You can request access, correction, anonymization or deletion of your data at any time: <a href={`mailto:${dpoEmail}`}>{dpoEmail}</a>.</p>
                <h3>7. Retention</h3>
                <p>Quote data is kept up to 24 months after last contact, unless a longer legal retention is required.</p>
                <h3>8. Data Protection Officer</h3>
                <p>Email: <a href={`mailto:${dpoEmail}`}>{dpoEmail}</a></p>
                <p className="muted">Last updated: April 2026.</p>
              </>
            )}
          </div>
        </div>
      </section>
    </div>
  );
}

function NotFoundPage({ t, go }) {
  const lang = (t && t.locale) || 'pt';
  const fromLegal = window.LEGAL && window.LEGAL[lang] && window.LEGAL[lang].notFound;
  const H1_FALLBACK   = { pt: 'Página não encontrada', en: 'Page not found', es: 'Página no encontrada' };
  const LEAD_FALLBACK = {
    pt: 'O link que você acessou não existe ou foi removido. Volte ao início ou explore nossas linhas de produto.',
    en: 'The page you requested does not exist or was moved. Go back home or explore our product lines.',
    es: 'La página que solicitó no existe o fue movida. Vuelva al inicio o explore nuestras líneas de producto.',
  };
  const HOME_BTN_FALLBACK = { pt: 'Início', en: 'Home', es: 'Inicio' };
  const h1 = (fromLegal && fromLegal.h1) || H1_FALLBACK[lang] || H1_FALLBACK.en;
  const lead = (fromLegal && fromLegal.lead) || LEAD_FALLBACK[lang] || LEAD_FALLBACK.en;
  const homeBtn = (fromLegal && fromLegal.homeBtn) || HOME_BTN_FALLBACK[lang] || HOME_BTN_FALLBACK.en;
  return (
    <div className="page-enter">
      <section className="page-hero">
        <div className="container" style={{ textAlign: 'center', paddingTop: 80, paddingBottom: 80 }}>
          <div className="mono-label" style={{ color: 'var(--brand)' }}>404</div>
          <h1 style={{ marginTop: 12 }}>{h1}</h1>
          <p className="lead" style={{ maxWidth: 520, margin: '16px auto 32px' }}>{lead}</p>
          <div style={{ display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
            <button className="btn btn-primary arrow" onClick={() => go('home')}>{homeBtn}</button>
            <button className="btn btn-secondary" onClick={() => go('products')}>{t.nav.products}</button>
          </div>
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { ErrorBoundary, WhatsAppFab, CookieBanner, PrivacyPage, NotFoundPage, InquiryDrawer });
