/**
 * Shared chat citation parser for ChatPage and ChatWidget.
 *
 * Parses [N] and [N,M] markers in streamed chat text into superscript
 * <Link> elements pointing to technique pages with optional section anchors.
 */

import React from "react";
import { Link } from "react-router-dom";
import type { ChatSource } from "../api/chat";

/** Matches [1], [2,3], [1,2,3] etc. */
const CITATION_RE = /\[(\d+(?:,\s*\d+)*)\]/g;

/**
 * Parse text containing [N] markers into React nodes with citation links.
 * Takes a styles object so both ChatPage and ChatWidget can pass their own CSS modules.
 * Expects `citationGroup` and `citationLink` keys in the styles object.
 */
export function parseChatCitations(
  text: string,
  sources: ChatSource[],
  styles: Record<string, string>,
): React.ReactNode[] {
  const nodes: React.ReactNode[] = [];
  let lastIndex = 0;

  for (const match of text.matchAll(CITATION_RE)) {
    const matchStart = match.index ?? 0;
    if (matchStart > lastIndex) {
      nodes.push(text.slice(lastIndex, matchStart));
    }

    const rawGroup = match[1];
    if (!rawGroup) continue;
    const indices = rawGroup.split(",").map((s) => parseInt(s.trim(), 10));
    const links: React.ReactNode[] = [];

    for (let i = 0; i < indices.length; i++) {
      const idx = indices[i]!;
      const source = sources[idx - 1]; // 1-based
      if (source) {
        if (i > 0) links.push(", ");
        const href = source.section_anchor
          ? `/techniques/${source.slug}#${source.section_anchor}`
          : `/techniques/${source.slug}`;
        links.push(
          <Link
            key={`${matchStart}-${idx}`}
            to={href}
            className={styles.citationLink}
            title={`${source.title}${source.section_heading ? ` — ${source.section_heading}` : ""}`}
          >
            {idx}
          </Link>,
        );
      } else {
        if (i > 0) links.push(", ");
        links.push(String(idx));
      }
    }

    nodes.push(
      <sup key={`cite-${matchStart}`} className={styles.citationGroup}>
        [{links}]
      </sup>,
    );

    lastIndex = matchStart + match[0].length;
  }

  if (lastIndex < text.length) {
    nodes.push(text.slice(lastIndex));
  }

  return nodes.length > 0 ? nodes : [text];
}
