// Markdown to HTML — tiny line-based parser (headings, emphasis, lists, code, links).

function mdToHtml(md) {
  const esc = (s) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  const safeHref = (url) => {
    const trimmed = url.trim().toLowerCase();
    if (trimmed.startsWith('javascript:') || trimmed.startsWith('data:') || trimmed.startsWith('vbscript:')) return '#';
    return url;
  };
  const inline = (s) => s
    .replace(/`([^`]+)`/g, (_, c) => `<code>${esc(c)}</code>`)
    .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
    .replace(/\*([^*]+)\*/g, '<em>$1</em>')
    .replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => `<a href="${safeHref(esc(url))}" rel="noopener noreferrer">${text}</a>`);

  const lines = md.split('\n');
  const out = [];
  let inCode = false, codeLang = '', codeBuf = [];
  let listType = null, listBuf = [];

  const flushList = () => {
    if (!listType) return;
    out.push(`<${listType}>${listBuf.map(i => `<li>${inline(i)}</li>`).join('')}</${listType}>`);
    listType = null; listBuf = [];
  };

  for (const raw of lines) {
    const line = raw;
    if (line.startsWith('```')) {
      if (inCode) {
        out.push(`<pre><code${codeLang ? ` class="lang-${codeLang}"` : ''}>${esc(codeBuf.join('\n'))}</code></pre>`);
        inCode = false; codeLang = ''; codeBuf = [];
      } else {
        flushList();
        inCode = true; codeLang = line.slice(3).trim();
      }
      continue;
    }
    if (inCode) { codeBuf.push(line); continue; }

    const h = line.match(/^(#{1,6})\s+(.*)/);
    if (h) { flushList(); out.push(`<h${h[1].length}>${inline(esc(h[2]))}</h${h[1].length}>`); continue; }

    const ul = line.match(/^\s*[-*]\s+(.*)/);
    const ol = line.match(/^\s*\d+\.\s+(.*)/);
    if (ul) {
      if (listType !== 'ul') flushList();
      listType = 'ul'; listBuf.push(esc(ul[1])); continue;
    }
    if (ol) {
      if (listType !== 'ol') flushList();
      listType = 'ol'; listBuf.push(esc(ol[1])); continue;
    }
    if (line.trim() === '') { flushList(); continue; }

    flushList();
    out.push(`<p>${inline(esc(line))}</p>`);
  }
  flushList();
  if (inCode && codeBuf.length) out.push(`<pre><code>${esc(codeBuf.join('\n'))}</code></pre>`);
  return out.join('\n');
}

window.TOOL_HANDLERS['md-to-html'] = function MdToHtmlTool() {
  const [md, setMd] = React.useState('# MiniMagics\n\nFast, **free** tools.\n\n- No uploads\n- Runs locally\n- Pure HTML [and](https://minimagics.app) CSS\n\n```js\nconst greet = (n) => `Hi ${n}`;\n```');
  const html = React.useMemo(() => mdToHtml(md), [md]);

  return (
    <div className="mini-tool">
      <div className="mini-grid">
        <div className="mini-left">
          <label className="mini-label">Markdown</label>
          <textarea className="mini-input mini-textarea" style={{ minHeight: 260, fontFamily: 'ui-monospace, monospace', fontSize: 13 }}
            value={md} onChange={(e) => setMd(e.target.value)} />
        </div>
        <div className="mini-right">
          <label className="mini-label">HTML</label>
          <textarea className="mini-input mini-textarea" readOnly style={{ minHeight: 260, fontFamily: 'ui-monospace, monospace', fontSize: 12 }}
            value={html} />
          <button className="btn btn-primary" style={{ marginTop: 10, width: '100%' }}
                  onClick={() => navigator.clipboard.writeText(html)}>
            <window.Icon name="doc" size={16} /> Copy HTML
          </button>
        </div>
      </div>
      <div style={{ marginTop: 18 }}>
        <div className="mini-label">Preview</div>
        <div style={{ padding: 16, border: '1px solid var(--id-border)', borderRadius: 10, background: 'var(--id-surface)' }}
             dangerouslySetInnerHTML={{ __html: html }} />
      </div>
    </div>
  );
};
