// 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) 'byt'                     (default)
const GenApp = () => {
  const [doctype, setDoctype] = React.useState(() => {
    if (window.__INITIAL_DOCTYPE) return window.__INITIAL_DOCTYPE;
    const u = new URLSearchParams(location.search);
    const raw = u.get('type') || 'byt';
    return raw === 'stavba' ? 'dom' : raw;
  });
  const defaultPartyType = (doctype === 'nebyt') ? 'company' : 'person';
  const [landlords, setLandlords] = React.useState([{ id: 1, type: defaultPartyType }]);
  const [tenants, setTenants] = React.useState([{ id: 2, type: defaultPartyType }]);

  // When doctype switches to/from 'nebyt', reset party types to the appropriate default.
  const prevDoctype = React.useRef(doctype);
  React.useEffect(() => {
    const prev = prevDoctype.current;
    prevDoctype.current = doctype;
    if (prev === doctype) return;
    const wasNebyt = prev === 'nebyt';
    const isNebyt = doctype === 'nebyt';
    if (wasNebyt !== isNebyt) {
      const t = isNebyt ? 'company' : 'person';
      setLandlords(ls => ls.map(l => ({ ...l, type: t })));
      setTenants(ts => ts.map(t2 => ({ ...t2, type: t })));
    }
  }, [doctype]);
  const [optionals, setOptionals] = React.useState({
    'c-inflation': true,        // inflačná doložka — zapnutá by default
    'c-smoking': true,         // fajčenie (bod 7.1)
    'c-pets': true,            // zvieratá (bod 7.2)
    'art-7': false,            // zmluvná pokuta — vypnutá
    'c-arbitration': true,     // rozhodcovská doložka — zapnutá by default
    'c-land-services': false,  // úhrady za služby pri pozemku — vypnuté by default
  });
  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);
  const [domBuildingType, setDomBuildingType] = React.useState('stavba');

  // 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);
  }, []);

  // Keď sa typ stavby zmení na garáž, vypni klauzulu fajčenia
  React.useEffect(() => {
    if (domBuildingType === 'garaz') {
      setOptionals(o => ({ ...o, 'c-smoking': false }));
    } else if (domBuildingType === 'stavba') {
      setOptionals(o => ({ ...o, 'c-smoking': true }));
    }
  }, [domBuildingType]);

  // 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]);
    };
    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 hidden/optional 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 optional clauses toggle (they change visible field count)
    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();
    };
  }, []);

  const toggleOptional = (id) => setOptionals(o => ({ ...o, [id]: !o[id] }));

  return (
    <>
      <GenHeader doctype={doctype} setDoctype={setDoctype} progress={progress} />
      <div className="gen-shell">
        <Paper
          doctype={doctype}
          landlords={landlords} setLandlords={setLandlords}
          tenants={tenants} setTenants={setTenants}
          optionals={optionals}
          setActiveArticle={(id) => { setActiveArticle(id); }}
          setActiveTipKey={setActiveTipKey}
          onTipClick={handleTipClick}
          activeTipKey={activeTipKey}
          domBuildingType={domBuildingType}
          setDomBuildingType={setDomBuildingType}
        />
        <RightSidebar
          doctype={doctype}
          optionals={optionals}
          toggleOptional={toggleOptional}
          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}
        optionals={optionals}
        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();
});
