// Centralized Markdown rendering utility
// Safe defaults per requirements: no inline HTML, no images, no code blocks, allow tables, links open in new tab with rel attributes

export function renderMarkdown(text, options = {}) {
  const opts = {
    allowInlineHTML: false,
    enableTables: true,
    enableBreaks: true,
    enableImages: false,
    enableCodeBlocks: false,
    allowInlineCode: false, // inline code currently not allowed
    linkTargetBlank: true,
    sidebarAccent: false,
    consoleWarnOnFallback: true,
    ...options
  };

  const input = typeof text === 'string' ? text : String(text ?? '');
  if (!input) return '';

  // Optional sidebar accent [[...]] -> keep content but mark with markdown strong (no raw HTML)
  const preprocessed = opts.sidebarAccent
    ? input.replace(/\[\[(.*?)\]\]/g, '**$1**')
    : input;

  try {
    const hasMarked = typeof window !== 'undefined' && window.marked;

    if (!hasMarked) {
      if (opts.consoleWarnOnFallback) {
        console.warn('renderMarkdown: Marked not available; falling back to plain text');
        console.log('renderMarkdown: input:', input);
      }
      return escapeToPlainHtml(preprocessed);
    }

    // Configure marked options defensively
    if (typeof window.marked?.use === 'function') {
      // Use the global singleton API exposed by Marked in browser builds
      const md = window.marked;

      // One-time registration of our token-based renderer; renderer reads dynamic opts from md.__evieOptions
      if (!md.__evieRendererApplied) {
        md.use({
          renderer: {
            link(token) {
              const { href, title, text } = token;
              const cur = md.__evieOptions || {};
              const safeHref = sanitizeUrl(href);
              if (!safeHref) return text || '';
              const t = cur.linkTargetBlank ? ' target="_blank"' : '';
              const rel = ' rel="noopener noreferrer nofollow"';
              const titleAttr = title ? ` title="${escapeHtmlAttr(title)}"` : '';
              return `<a href="${escapeHtmlAttr(safeHref)}"${t}${rel}${titleAttr}>${text}</a>`;
            },
            image(token) {
              const { href, title, text } = token;
              const cur = md.__evieOptions || {};
              if (!cur.enableImages) return text ? escapeToPlainHtml(text) : '';
              const safeHref = sanitizeUrl(href);
              if (!safeHref) return text ? escapeToPlainHtml(text) : '';
              const titleAttr = title ? ` title="${escapeHtmlAttr(title)}"` : '';
              return `<img src="${escapeHtmlAttr(safeHref)}" alt="${escapeHtmlAttr(text || '')}"${titleAttr} />`;
            },
            code(token) {
              const { text } = token;
              // Render as escaped pre/code regardless of highlighting
              return `<pre><code>${escapeToPlainHtml(text)}</code></pre>`;
            },
            codespan(token) {
              const { text } = token;
              const cur = md.__evieOptions || {};
              if (!cur.allowInlineCode) return escapeToPlainHtml(text);
              return `<code>${escapeToPlainHtml(text)}</code>`;
            },
            table(token) {
              const cur = md.__evieOptions || {};
              if (cur.enableTables) return undefined; // default rendering
              const headerCells = token.header?.map(h => h.text).join(' | ') || '';
              const rowTexts = (token.rows || []).map(row => row.map(c => c.text).join(' | '));
              const all = [headerCells, ...rowTexts].filter(Boolean).join('\n');
              return `<p>${escapeToPlainHtml(all)}</p>`;
            }
          }
        });
        md.__evieRendererApplied = true;
      }

      // Set dynamic options per render
      md.__evieOptions = {
        allowInlineHTML: !!opts.allowInlineHTML,
        enableTables: !!opts.enableTables,
        enableBreaks: !!opts.enableBreaks,
        enableImages: !!opts.enableImages,
        enableCodeBlocks: !!opts.enableCodeBlocks,
        allowInlineCode: !!opts.allowInlineCode,
        linkTargetBlank: !!opts.linkTargetBlank
      };

      md.setOptions({
        gfm: true,
        breaks: !!opts.enableBreaks,
        headerIds: false,
        mangle: false
      });

      const html = md.parse(preprocessed);
      const sanitized = sanitizeHtml(html);
      return sanitized;
    }

    // Fallback older API: window.marked is a function
    const html = typeof window.marked === 'function' ? window.marked(preprocessed) : String(preprocessed);
    const sanitized = sanitizeHtml(html);
    return sanitized;
  } catch (err) {
    console.warn('renderMarkdown: error while rendering; falling back to plain text', err);
    return escapeToPlainHtml(preprocessed);
  }
}

// Very small sanitizer if DOMPurify is not provided globally. Prefer window.DOMPurify if available.
function sanitizeHtml(html) {
  try {
    if (typeof window !== 'undefined' && window.DOMPurify && typeof window.DOMPurify.sanitize === 'function') {
      return window.DOMPurify.sanitize(html, {
        USE_PROFILES: { html: true },
        ADD_ATTR: ['target', 'rel', 'title'],
        ALLOWED_TAGS: undefined // use default safe set
      });
    }
  } catch (e) {
    console.warn('sanitizeHtml: DOMPurify error, using basic sanitizer', e);
  }
  // Basic sanitizer: strip script tags and on* attributes
  return String(html)
    .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
    .replace(/ on[a-z]+="[^"]*"/gi, '')
    .replace(/ on[a-z]+='[^']*'/gi, '');
}

// Escape plain text to safe HTML
function escapeToPlainHtml(text) {
  return String(text)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
    .replace(/\n/g, '<br>');
}

function sanitizeUrl(href) {
  if (!href) return '';
  try {
    const str = String(href).trim();
    const lower = str.toLowerCase();
    // Block javascript: and data: except maybe safe data images (we disable images anyway)
    if (lower.startsWith('javascript:')) return '';
    if (lower.startsWith('data:')) return '';
    if (lower.startsWith('vbscript:')) return '';
    return str;
  } catch (e) {
    return '';
  }
}

function escapeHtmlAttr(s) {
  return String(s)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}
