// Generator app — mounted on pages that render the contract editor.
// Initial doctype resolution:
//   1) window.__INITIAL_DOCTYPE  (set inline by /vzor/*.html)
//   2) ?type= URL param          (back-compat on /vzor.html)
//   3) 'navrh'                   (default)
const GenApp = () => {
  const [doctype, setDoctype] = React.useState(() => {
    if (window.__INITIAL_DOCTYPE) return window.__INITIAL_DOCTYPE;
    const u = new URLSearchParams(location.search);
    return u.get('type') || 'navrh';
  });
  const [navrhovatel, setNavrhovatel] = React.useState({ id: 1, type: 'person' });
  const [odporca, setOdporca] = React.useState({ id: 2, type: 'person' });

  const [activeArticle, setActiveArticle] = React.useState('art-1');
  const [activeTipKey, setActiveTipKey] = React.useState(null);
  const [tipModalKey, setTipModalKey] = React.useState(null);
  const [progress, setProgress] = React.useState(0);

  // Click na TIP tlačidlo: aktualizuj sidebar (desktop) aj otvor modal (mobile).
  // Scroll-spy v Paper si naďalej volá iba setActiveTipKey, takže modal nereaguje
  // na rolovanie — otvorí sa len na zámerný klik.
  const handleTipClick = React.useCallback((key) => {
    setActiveTipKey(key);
    setTipModalKey(key);
  }, []);

  // Pri zmene doctype aktualizuj URL (history.pushState) a document.title
  // podľa konfigurácie v config.js. Pokrýva aj klik na tab v GenHeader aj
  // programatický setDoctype. Na prvom renderi (ak URL už sedí) sa push nepustí.
  React.useEffect(() => {
    const url = window.VZOR_URLS && window.VZOR_URLS[doctype];
    const title = window.VZOR_TITLES && window.VZOR_TITLES[doctype];
    if (title) {
      document.title = title.replace(/\(\d{4}\)/, '(' + new Date().getFullYear() + ')');
    }
    if (url && location.pathname !== url) {
      history.pushState({ doctype }, '', url);
    }
  }, [doctype]);

  // Reverzné mapovanie pre tlačidlo Späť/Dopredu v prehliadači:
  // popstate → nájdi doctype podľa aktuálnej pathname a presuň naň stav.
  React.useEffect(() => {
    const handler = () => {
      const entries = Object.entries(window.VZOR_URLS || {});
      const match = entries.find(([, url]) => url === location.pathname);
      if (match && match[0] !== doctype) setDoctype(match[0]);
      else if (!match && doctype !== 'navrh') setDoctype('navrh');
    };
    window.addEventListener('popstate', handler);
    return () => window.removeEventListener('popstate', handler);
  }, [doctype]);

  // Compute progress from filled .ed fields inside .paper (+ selects count as pre-filled)
  React.useEffect(() => {
    const compute = () => {
      const paper = document.querySelector('article.paper');
      if (!paper) return;
      // Only count visible fields (skip fields inside currently hidden conditional sections)
      const eds = Array.from(paper.querySelectorAll('.ed[data-placeholder]'))
        .filter(el => el.offsetParent !== null); // visible only
      if (!eds.length) { setProgress(0); return; }
      const filled = eds.filter(el => (el.textContent || '').trim().length > 0).length;
      const pct = Math.round((filled / eds.length) * 100);
      setProgress(pct);
    };

    // Initial compute after React settles
    const t = setTimeout(compute, 150);

    // Listen for any input inside the paper (bubbling)
    const handler = () => compute();
    document.addEventListener('input', handler, true);
    // Also recompute when selects change (they're native <select>)
    document.addEventListener('change', handler, true);
    // And when conditional sekcie sa objavia/zmiznú (wizard q1/q2/q3, sample
    // panely) — menia sa aj počty viditeľných polí, treba prepočítať progress.
    const mo = new MutationObserver(() => { clearTimeout(window.__progTimer); window.__progTimer = setTimeout(compute, 50); });
    const paper = document.querySelector('article.paper');
    if (paper) mo.observe(paper, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'] });

    return () => {
      clearTimeout(t);
      document.removeEventListener('input', handler, true);
      document.removeEventListener('change', handler, true);
      mo.disconnect();
    };
  }, []);

  return (
    <>
      <GenHeader doctype={doctype} setDoctype={setDoctype} progress={progress} />
      <div className="gen-shell">
        {/* Paper variant podľa doctype. Defenzívny fallback: ak je požadovaný
            variant nenahraný touto stránkou (napr. tab-klik pred plnou navigáciou),
            padneme na klasický Paper namiesto crash-u. */}
        {(() => {
          const PaperVariant =
            (doctype === 'navrh-deti' && window.PaperDeti) ? window.PaperDeti :
            (doctype === 'dohoda' && window.PaperDohoda)   ? window.PaperDohoda :
                                                              Paper;
          return (
            <PaperVariant
              doctype={doctype}
              navrhovatel={navrhovatel} setNavrhovatel={setNavrhovatel}
              odporca={odporca} setOdporca={setOdporca}
              setActiveArticle={(id) => { setActiveArticle(id); }}
              setActiveTipKey={setActiveTipKey}
              onTipClick={handleTipClick}
              activeTipKey={activeTipKey}
            />
          );
        })()}
        <RightSidebar
          doctype={doctype}
          activeArticle={activeArticle}
          activeTipKey={activeTipKey}
          clearTipKey={() => setActiveTipKey(null)}
        />
      </div>
      {window.LEGAL_TEXTS && window.LEGAL_TEXTS[doctype] && (
        <section
          className="legal-article"
          dangerouslySetInnerHTML={{ __html: window.LEGAL_TEXTS[doctype].html }}
        />
      )}
      <TipModal
        doctype={doctype}
        tipKey={tipModalKey}
        onClose={() => { setTipModalKey(null); setActiveTipKey(null); }}
      />
    </>
  );
};

ReactDOM.createRoot(document.getElementById('gen-root')).render(<GenApp />);

// ------------------------------------------------------------
// Copy / "Save as Word" sanitizer.
// When users select-and-copy paragraphs from the paper, browsers
// serialize EVERY <option> inside each <select> — producing
// garbage like "zakázanémožné len s písomným súhlasom...". Here
// we intercept `copy` events on the paper and rewrite the
// clipboard so each select contributes only its CURRENT label.
// ------------------------------------------------------------
document.addEventListener('copy', (e) => {
  const sel = document.getSelection();
  if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return;
  const range = sel.getRangeAt(0);
  const paper = document.querySelector('article.paper');
  if (!paper || !paper.contains(range.commonAncestorContainer) && !paper.contains(range.startContainer)) return;

  // Clone the selected fragment, then collapse each <select> to the selected option only.
  const frag = range.cloneContents();
  const wrap = document.createElement('div');
  wrap.appendChild(frag);

  // cloneContents() loses the select's `value` property, but <option selected> is preserved
  // in the cloned DOM only if the original HAD the attribute. React sets `value` on the
  // <select> via the DOM property, not the attribute — so we look up each cloned select's
  // live counterpart and read its real value.
  const liveSelects = paper.querySelectorAll('select.ed-select');
  const clonedSelects = wrap.querySelectorAll('select.ed-select');
  // Map cloned → live by index among all selects that intersect the selection.
  // The clone preserves order, so we walk live selects and pick the ones visually
  // inside the selection range.
  const liveInRange = [];
  for (const s of liveSelects) {
    const r = document.createRange();
    r.selectNode(s);
    if (range.compareBoundaryPoints(Range.END_TO_START, r) <= 0 &&
        range.compareBoundaryPoints(Range.START_TO_END, r) >= 0) {
      liveInRange.push(s);
    }
  }
  clonedSelects.forEach((cs, i) => {
    const live = liveInRange[i];
    const val = live ? live.value : cs.value;
    // Remove every <option> except the selected one; replace <select> with the
    // bare label text so plain-text copy doesn't show "▼" chrome either.
    const picked = Array.from(cs.querySelectorAll('option')).find(o => o.value === val)
                || cs.querySelector('option[selected]')
                || cs.querySelector('option');
    const label = picked ? picked.textContent : '';
    const textNode = document.createTextNode(label);
    cs.parentNode.replaceChild(textNode, cs);
  });

  // Strip TIP buttons and other non-content chrome.
  wrap.querySelectorAll('.tip-btn, .tip-pin, .party-remove, .party-add, .seg-toggle, .seg-add, .no-copy, .party-type-switches').forEach(el => el.remove());

  const html = wrap.innerHTML;
  const text = wrap.innerText || wrap.textContent || '';

  e.clipboardData.setData('text/html', html);
  e.clipboardData.setData('text/plain', text);
  e.preventDefault();
});
