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

// ── Mermaid init ──────────────────────────────────────
if (typeof mermaid !== 'undefined') {
  mermaid.initialize({
    startOnLoad: false, theme: 'base',
    themeVariables: {
      background: '#131221', primaryColor: '#1e1a32', primaryTextColor: '#e4e1f0',
      primaryBorderColor: '#2e2b48', lineColor: '#6050a0', secondaryColor: '#1c1a2e',
      tertiaryColor: '#0f0e1c', edgeLabelBackground: '#131221', clusterBkg: '#1c1a2e',
      titleColor: '#c0b0e8', fontSize: '14px', fontFamily: 'DM Sans, system-ui, sans-serif'
    }
  });
}

function runMermaid(container) {
  if (!container || typeof mermaid === 'undefined') return;
  const nodes = [...container.querySelectorAll('.mermaid:not([data-processed])')];
  if (!nodes.length) return;
  setTimeout(() => {
    mermaid.run({ nodes }).then(() => {
      nodes.forEach(node => {
        try {
          const lm = JSON.parse(node.getAttribute('data-link-map') || '{}');
          Object.entries(lm).forEach(([label, slug]) => {
            node.querySelectorAll('.nodeLabel,.edgeLabel,text,tspan').forEach(el => {
              if (el.textContent.trim() === label) {
                el.style.cursor = 'pointer'; el.style.fill = 'var(--accent)';
                el.addEventListener('click', e => { e.stopPropagation(); window.location.hash = '#/wiki/' + slug; });
              }
            });
          });
        } catch {}
      });
    }).catch(() => {});
  }, 80);
}

function infoboxToHTML(raw) {
  const fields = {};
  raw.trim().split('\n').forEach(line => {
    const c = line.indexOf(':'); if (c < 0) return;
    const k = line.slice(0, c).trim(), v = line.slice(c + 1).trim();
    if (k) fields[k] = v;
  });
  const init = (fields.name || 'W')[0].toUpperCase();
  const pv = v => v.replace(/\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g, (_, name, alias) => {
    const d = (alias || name).trim(), s = name.trim().toLowerCase().replace(/[^a-z0-9/]+/g, '-').replace(/^-+|-+$/g, '');
    return `<a href="#/wiki/${s}" class="wiki-link" data-slug="${s}">${d}</a>`;
  });
  const entries = Object.entries(fields).filter(([k]) => k !== 'image' && k !== 'name');
  return `<div class="infobox">${fields.image ? `<img src="${fields.image}" alt="${fields.name || ''}" class="infobox-img">` : `<div class="infobox-img-placeholder">${init}</div>`}${fields.name ? `<div class="infobox-name">${fields.name}</div>` : ''}<table class="infobox-table"><tbody>${entries.map(([k, v]) => `<tr><th>${k}</th><td>${pv(v)}</td></tr>`).join('')}</tbody></table></div>`;
}

function processMarkdown(text) {
  if (!text) return '';
  const iboxes = [], codeBlocks = [];
  let r = text.replace(/:::infobox\n?([\s\S]*?):::/g, (_, c) => { const i = iboxes.length; iboxes.push(c); return `\n\nIBPH_${i}\n\n`; });
  r = r.replace(/```(\w*)\n?([\s\S]*?)```/g, (_, lang, code) => { const i = codeBlocks.length; codeBlocks.push({ lang: lang.trim(), code }); return `\n\nCBPH_${i}\n\n`; });
  r = r.replace(/\[\[([^\]\n]+?)\]\]/g, (_, c) => { const [name, alias] = c.split('|'); const d = (alias || name).trim(); const s = name.trim().toLowerCase().replace(/[^a-z0-9/]+/g, '-').replace(/^-+|-+$/g, ''); return `<a href="#/wiki/${s}" class="wiki-link" data-slug="${s}">${d}</a>`; });
  let html = marked.parse(r);
  html = html.replace(/<h([1-6])>(.*?)<\/h\1>/gi, (_, l, c) => { const id = c.replace(/<[^>]*>/g, '').toLowerCase().replace(/[^a-z0-9\s-]/g, '').trim().replace(/\s+/g, '-'); return `<h${l} id="${id}">${c}</h${l}>`; });
  html = html.replace(/<p>\s*CBPH_(\d+)\s*<\/p>|CBPH_(\d+)/g, (_, i1, i2) => {
    const { lang, code } = codeBlocks[parseInt(i1 ?? i2)];
    if (lang === 'mermaid') {
      const lm = {}; const p = code.replace(/\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g, (__, name, alias) => { const d = (alias || name).trim(), s = name.trim().toLowerCase().replace(/[^a-z0-9/]+/g, '-').replace(/^-+|-+$/g, ''); lm[d] = s; return d; });
      return `<div class="mermaid" data-link-map='${JSON.stringify(lm).replace(/'/g, "&#39;")}'>${p}</div>`;
    }
    const esc = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    return `<pre><code${lang ? ` class="language-${lang}"` : ''}>${esc}</code></pre>`;
  });
  html = html.replace(/<p>\s*IBPH_(\d+)\s*<\/p>|IBPH_(\d+)/g, (_, i1, i2) => infoboxToHTML(iboxes[parseInt(i1 ?? i2)]));
  return html;
}

function extractTOC(text) {
  return (text || '').split('\n').map(l => { const m = l.match(/^(#{1,3})\s+(.+)$/); return m ? { depth: m[1].length, text: m[2].trim(), id: m[2].trim().toLowerCase().replace(/[^a-z0-9\s-]/g, '').trim().replace(/\s+/g, '-') } : null; }).filter(Boolean);
}

function formatDate(d) {
  if (!d) return '';
  return new Date(d).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
}

function TOC({ headings }) {
  const [active, setActive] = useState('');
  useEffect(() => {
    const obs = new IntersectionObserver(es => { for (const e of es) if (e.isIntersecting) setActive(e.target.id); }, { rootMargin: '-20% 0px -70% 0px' });
    headings.forEach(h => { const el = document.getElementById(h.id); if (el) obs.observe(el); });
    return () => obs.disconnect();
  }, [headings]);
  if (!headings.length) return null;
  return (
    <aside className="toc-wrap">
      <div className="toc-label">On this page</div>
      <ul className="toc-list">
        {headings.map(h => (
          <li key={h.id}>
            <div className={`toc-item depth-${h.depth}${active === h.id ? ' active' : ''}`}
              onClick={() => { setActive(h.id); document.getElementById(h.id)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }}>
              {h.text}
            </div>
          </li>
        ))}
      </ul>
    </aside>
  );
}

function Lightbox({ src, alt, onClose }) {
  useEffect(() => { const fn = e => e.key === 'Escape' && onClose(); window.addEventListener('keydown', fn); return () => window.removeEventListener('keydown', fn); }, []);
  return (
    <div className="lightbox" onClick={onClose}>
      <img src={src} alt={alt || ''} onClick={e => e.stopPropagation()} />
      <button className="lightbox-close" onClick={onClose}>×</button>
    </div>
  );
}

function HistoryPanel({ versions, onRestore, onClose }) {
  return (
    <div className="history-panel open">
      <div className="history-header">
        <span>Page History</span>
        <button className="btn btn-ghost btn-sm" onClick={onClose}>Close</button>
      </div>
      {versions.length === 0
        ? <div style={{ color: 'var(--text-muted)', fontSize: 13 }}>No saved versions yet.</div>
        : [...versions].reverse().map((v, i) => (
          <div key={v.ts} className="history-item" onClick={() => onRestore(v.snapshot)}>
            <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--text)' }}>{new Date(v.ts).toLocaleString()}</div>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>{v.snapshot.content?.length || 0} chars · click to restore</div>
          </div>
        ))
      }
    </div>
  );
}

function ArticlePage({ slug, user, onEdit, onDelete, onNavigate, history, onRestore }) {
  const [page, setPage] = useState(null);
  const [backlinks, setBacklinks] = useState([]);
  const [loading, setLoading] = useState(true);
  const [notFound, setNotFound] = useState(false);
  const [lightbox, setLightbox] = useState(null);
  const [showHistory, setShowHistory] = useState(false);
  const containerRef = useRef(null);

  useEffect(() => {
    setLoading(true); setNotFound(false); setPage(null); setBacklinks([]);
    const token = localStorage.getItem('token');
    const headers = token ? { Authorization: `Bearer ${token}` } : {};
    Promise.all([
      fetch(`/api/pages/${slug}`, { headers }),
      fetch(`/api/backlinks/${slug}`, { headers })
    ]).then(async ([pageRes, blRes]) => {
      if (!pageRes.ok) { setNotFound(true); setLoading(false); return; }
      const [pageData, blData] = await Promise.all([pageRes.json(), blRes.json()]);
      setPage(pageData); setBacklinks(blData); setLoading(false);
      document.title = (pageData.meta?.title || slug) + ' — Wiki';
    }).catch(() => { setNotFound(true); setLoading(false); });
  }, [slug]);

  const html = useMemo(() => page ? processMarkdown(page.content) : '', [page]);
  useEffect(() => { runMermaid(containerRef.current); }, [html]);

  if (loading) return (
    <div className="article-wrap">
      <div className="article-body">
        {[60, 30, 100, 85, 90, 70].map((w, i) => <div key={i} className="skeleton" style={{ height: i === 0 ? 44 : 14, width: w + '%', marginBottom: 12 }}></div>)}
      </div>
    </div>
  );

  if (notFound) return (
    <div className="empty-state">
      <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>
      <div className="empty-state-title">Page not found</div>
      <div className="empty-state-desc">"{slug}" doesn't exist yet.</div>
      {user?.role === 'admin' && <button className="btn btn-primary btn-sm" style={{ marginTop: 8 }} onClick={() => onEdit(slug)}>Create this page</button>}
    </div>
  );

  const title = page.meta?.title || slug.split('/').pop().replace(/-/g, ' ');
  const tags = page.meta?.tags ? (Array.isArray(page.meta.tags) ? page.meta.tags : [page.meta.tags]) : [];
  const toc = extractTOC(page.content);

  return (
    <div className="article-wrap">
      <div className="article-body">
        {page.meta?.draft === 'true' && <div className="draft-banner"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg>Draft — not visible to non-admin users</div>}
        <div className="article-header">
          <h1 className="article-title">{title}</h1>
          <div className="article-meta">
            {page.modified && <span>Updated {formatDate(page.modified)}</span>}
            {tags.length > 0 && <div className="tags">{tags.map(t => <span key={t} className="tag">{t}</span>)}</div>}
            {user?.role === 'admin' && (
              <div className="article-actions">
                <button className="btn btn-ghost btn-sm" onClick={() => onEdit(slug)}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>Edit</button>
                <button className="btn btn-ghost btn-sm" onClick={() => setShowHistory(h => !h)} style={showHistory ? { color: 'var(--accent)', borderColor: 'var(--accent)' } : {}}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>History</button>
                <button className="btn btn-danger btn-sm" onClick={() => onDelete(slug, title)}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>Delete</button>
              </div>
            )}
          </div>
        </div>
        <div ref={containerRef} className="markdown-body" dangerouslySetInnerHTML={{ __html: html }}
          onClick={e => {
            if (e.target.tagName === 'IMG') { setLightbox({ src: e.target.src, alt: e.target.alt }); return; }
            const a = e.target.closest('a.wiki-link');
            if (a) { e.preventDefault(); onNavigate('#/wiki/' + a.dataset.slug); }
          }} />
        {backlinks.length > 0 && (
          <div className="backlinks">
            <div className="backlinks-title">Referenced by {backlinks.length} page{backlinks.length !== 1 ? 's' : ''}</div>
            <div className="backlinks-list">
              {backlinks.map(b => <a key={b.slug} className="backlink-chip" href={'#/wiki/' + b.slug} onClick={e => { e.preventDefault(); onNavigate('#/wiki/' + b.slug); }}><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>{b.title}</a>)}
            </div>
          </div>
        )}
      </div>
      {toc.length > 1 && <TOC headings={toc} />}
      {lightbox && <Lightbox src={lightbox.src} alt={lightbox.alt} onClose={() => setLightbox(null)} />}
      {showHistory && history && <HistoryPanel versions={history} onRestore={snap => { onRestore(slug, snap); setShowHistory(false); }} onClose={() => setShowHistory(false)} />}
    </div>
  );
}

Object.assign(window, { ArticlePage, processMarkdown, runMermaid, extractTOC, infoboxToHTML, TOC });
