/**
 * Parser for line-level code references.
 * Handles formats like:
 *   file.rs:42
 *   src/main.rs:10-20
 *   #L42
 *   #L42-L48
 *   src/app.tsx:5
 */

export interface CodeRef {
  /** File path (e.g. "src/main.rs") */
  filePath: string;
  /** Start line number (1-based) */
  startLine: number;
  /** End line number (inclusive, same as startLine for single line */
  endLine: number;
  /** The original reference text */
  raw: string;
}

/** Parse a code reference string into structured data. */
export function parseCodeRef(ref: string): CodeRef | null {
  // Format: path:start[-end]
  // Example: src/main.rs:42, src/main.rs:10-20
  const lineRangeMatch = ref.match(/^(.+):(\d+)(?:-(\d+))?$/);
  if (lineRangeMatch) {
    const [, filePath, startStr, endStr] = lineRangeMatch;
    const startLine = parseInt(startStr, 10);
    const endLine = endStr ? parseInt(endStr, 10) : startLine;
    if (startLine > 0 && endLine >= startLine) {
      return { filePath: filePath.trim(), startLine, endLine, raw: ref };
    }
  }

  // Format: #L42 or #L42-L48 (GitHub-style)
  const ghMatch = ref.match(/^#L(\d+)(?:-L(\d+))?$/i);
  if (ghMatch) {
    const [, startStr, endStr] = ghMatch;
    const startLine = parseInt(startStr, 10);
    const endLine = endStr ? parseInt(endStr, 10) : startLine;
    if (startLine > 0 && endLine >= startLine) {
      return { filePath: '', startLine, endLine, raw: ref };
    }
  }

  return null;
}

/** Extract all code references from a text string. */
export function extractCodeRefs(text: string): CodeRef[] {
  const refs: CodeRef[] = [];

  // Match file:line or file:line-line patterns
  const linePattern = /([^\s:]+:\d+(?:-\d+)?)/g;
  let match;
  while ((match = linePattern.exec(text)) !== null) {
    const parsed = parseCodeRef(match[1]);
    if (parsed) refs.push(parsed);
  }

  // Match #Lnn or #Lnn-Lmm (GitHub-style)
  const ghPattern = /#L(\d+)(?:-L(\d+))?/gi;
  while ((match = ghPattern.exec(text)) !== null) {
    const startLine = parseInt(match[1], 10);
    const endLine = match[2] ? parseInt(match[2], 10) : startLine;
    if (startLine > 0 && endLine >= startLine) {
      refs.push({ filePath: '', startLine, endLine, raw: match[0] });
    }
  }

  return refs;
}

/** Format a code reference as a display string. */
export function formatCodeRef(ref: CodeRef): string {
  if (ref.endLine === ref.startLine) {
    return `${ref.filePath}:${ref.startLine}`;
  }
  return `${ref.filePath}:${ref.startLine}-${ref.endLine}`;
}
