/**
 * @license
 * Copyright 2026 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {DiffInfo} from '../../../types/diff';
import {CommentSide, Side} from '../../../constants/constants';
import {CommentThread, PatchRange} from '../../../types/common';
import {isInBaseOfPatchRange} from '../../../utils/comment-util';
import {getDiffLines} from '../../../utils/diff-util';
import {html, TemplateResult} from 'lit';
import {Lexer, Marked, Token, Tokens} from 'marked';

export type DiffBlockStatus = 'unchanged' | 'added' | 'deleted' | 'modified';

export type WrapperTag =
  | 'p'
  | 'li'
  | 'th'
  | 'td'
  | 'h1'
  | 'h2'
  | 'h3'
  | 'h4'
  | 'h5'
  | 'h6';

export type MarkdownToken = Token & {
  startLine?: number;
  endLine?: number;
};

export interface AlignedDiffRow {
  status: DiffBlockStatus;
  leftToken?: MarkdownToken;
  rightToken?: MarkdownToken;
  leftHtml?: TemplateResult;
  rightHtml?: TemplateResult;
  leftStartLine?: number;
  leftEndLine?: number;
  rightStartLine?: number;
  rightEndLine?: number;
}

export interface AlignedDiffRowWithThreads extends AlignedDiffRow {
  leftThreads: CommentThread[];
  rightThreads: CommentThread[];
}

export interface InlineDiffSegment {
  text: string;
  type: 'common' | 'added' | 'deleted';
}

/**
 * Maximum normalized edit distance (0.0 = identical, 1.0 = completely disjoint)
 * for two blocks, lines, or list items to be inferred as homologous
 * modifications of one another (inspired by dandavison/delta's
 * --max-line-distance, which defaults to 0.6).
 */
export const DEFAULT_MAX_HOMOLOGOUS_DISTANCE = 0.6;

/** Reconstruct the entire file content from diff chunks for the given side. */
export function reconstructFileContent(diff: DiffInfo, side: Side): string {
  return getDiffLines(diff, side).join('\n');
}

/** Parse markdown text into top-level block tokens with line number metadata. */
export function parseMarkdownBlocks(markdown: string): MarkdownToken[] {
  if (!markdown) return [];
  const marked = new Marked();
  const tokens = marked.lexer(markdown);
  const result: MarkdownToken[] = [];
  let curLine = 1;
  for (const t of tokens) {
    const raw = t.raw;
    const newlineCount = (raw.match(/\n/g) || []).length;
    const startLine = curLine;
    const endLine = curLine + newlineCount - (raw.endsWith('\n') ? 1 : 0);
    curLine += newlineCount;
    if (t.type === 'space') {
      continue;
    }
    (t as MarkdownToken).startLine = startLine;
    (t as MarkdownToken).endLine = Math.max(startLine, endLine);
    result.push(t);
  }
  return result;
}

function isMarkdownLinkToken(token: Token): token is Tokens.Link {
  return token.type === 'link';
}

function isInlineContainerToken(
  token: Token
): token is (Tokens.Strong | Tokens.Em | Tokens.Del) & {tokens: Token[]} {
  return (
    (token.type === 'strong' || token.type === 'em' || token.type === 'del') &&
    'tokens' in token &&
    Array.isArray(token.tokens)
  );
}

function getContainerDelimiters(token: Token & {tokens?: Token[]}): {
  openDelim: string;
  closeDelim: string;
} {
  const innerRaw = (token.tokens ?? []).map(t => t.raw).join('');
  if (!innerRaw) {
    return {openDelim: '', closeDelim: ''};
  }
  const symIdx = Math.floor((token.raw.length - innerRaw.length) / 2);
  if (
    symIdx > 0 &&
    token.raw.slice(symIdx, symIdx + innerRaw.length) === innerRaw
  ) {
    return {
      openDelim: token.raw.slice(0, symIdx),
      closeDelim: token.raw.slice(symIdx + innerRaw.length),
    };
  }
  const idx = token.raw.indexOf(innerRaw);
  if (idx >= 0) {
    return {
      openDelim: token.raw.slice(0, idx),
      closeDelim: token.raw.slice(idx + innerRaw.length),
    };
  }
  return {openDelim: '', closeDelim: ''};
}

function tokenizeInlineAstTokens(tokens: Token[], result: string[]) {
  for (const token of tokens) {
    if (token.type === 'codespan' || isMarkdownLinkToken(token)) {
      result.push(token.raw);
    } else if (isInlineContainerToken(token)) {
      const {openDelim, closeDelim} = getContainerDelimiters(token);
      if (openDelim) result.push(openDelim);
      tokenizeInlineAstTokens(token.tokens, result);
      if (closeDelim) result.push(closeDelim);
    } else {
      const subTokens = token.raw.match(/\s+|[^\s\w]+|\w+/g);
      if (subTokens) {
        result.push(...subTokens);
      }
    }
  }
}

/**
 * Tokenize text using Marked's inline AST lexer (`Lexer.lexInline`) so
 * markdown links and inline code spans remain atomic AST units (including when
 * nested inside container tokens such as `strong`, `em`, or `del`) while plain
 * text nodes are split into words, whitespace, and punctuation for
 * fine-grained inline diffing.
 */
export function tokenizeWords(text: string): string[] {
  if (!text) return [];
  const inlineTokens = Lexer.lexInline(text);
  const result: string[] = [];
  tokenizeInlineAstTokens(inlineTokens, result);
  return result;
}

const SAFE_URL_SCHEMES = new Set(['http:', 'https:']);

/**
 * Sanitize a markdown link href so dangerous schemes (such as `javascript:`,
 * `data:`, or `vbscript:`) cannot execute when rendered in an `<a>` tag.
 */
export function sanitizeMarkdownUrl(url: string): string {
  const trimmed = url.trim();
  if (!trimmed) return '';
  try {
    const parsed = new URL(trimmed);
    if (SAFE_URL_SCHEMES.has(parsed.protocol.toLowerCase())) {
      return trimmed;
    }
    return 'about:invalid#zClosurez';
  } catch {
    // Relative URL (no explicit scheme); reject control-character-obfuscated schemes.
    // eslint-disable-next-line no-control-regex
    const normalized = trimmed.replace(/[\u0000-\u0020]+/g, '');
    if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(normalized)) {
      return 'about:invalid#zClosurez';
    }
    return trimmed;
  }
}

function renderCodeSpanToken(token: Tokens.Codespan): TemplateResult {
  return html`<code>${token.text}</code>`;
}

function renderInlineContainerTag(
  type: 'strong' | 'em' | 'del',
  content: unknown
): TemplateResult {
  switch (type) {
    case 'strong':
      return html`<strong>${content}</strong>`;
    case 'em':
      return html`<em>${content}</em>`;
    case 'del':
      return html`<del>${content}</del>`;
  }
}

function renderHighlightTag(
  tag: 'del' | 'ins',
  highlightClass: string,
  content: unknown
): TemplateResult {
  return tag === 'del'
    ? html`<del class=${highlightClass}>${content}</del>`
    : html`<ins class=${highlightClass}>${content}</ins>`;
}

function renderWrapperTag(tag: WrapperTag, content: unknown): TemplateResult {
  switch (tag) {
    case 'h1':
      return html`<h1>${content}</h1>`;
    case 'h2':
      return html`<h2>${content}</h2>`;
    case 'h3':
      return html`<h3>${content}</h3>`;
    case 'h4':
      return html`<h4>${content}</h4>`;
    case 'h5':
      return html`<h5>${content}</h5>`;
    case 'h6':
      return html`<h6>${content}</h6>`;
    case 'li':
      return html`<li>${content}</li>`;
    case 'th':
      return html`<th>${content}</th>`;
    case 'td':
      return html`<td>${content}</td>`;
    case 'p':
      return html`<p>${content}</p>`;
  }
}

function renderInlineAstTokens(
  tokens: Token[],
  options: {includeLinks: boolean}
): TemplateResult {
  const parts: Array<TemplateResult | string> = [];
  for (const token of tokens) {
    if (token.type === 'codespan') {
      parts.push(renderCodeSpanToken(token as Tokens.Codespan));
    } else if (options.includeLinks && isMarkdownLinkToken(token)) {
      const labelContent =
        token.tokens && token.tokens.length > 0
          ? renderInlineAstTokens(token.tokens, {
              includeLinks: false,
            })
          : token.text || token.href;
      const safeHref = sanitizeMarkdownUrl(token.href);
      parts.push(html`<a href=${safeHref}>${labelContent}</a>`);
    } else if (isInlineContainerToken(token)) {
      parts.push(
        renderInlineContainerTag(
          token.type,
          renderInlineAstTokens(token.tokens, options)
        )
      );
    } else if (token.type === 'br') {
      parts.push(html`<br />`);
    } else if (token.type === 'escape') {
      parts.push((token as Tokens.Escape).text);
    } else if (
      'tokens' in token &&
      token.tokens &&
      token.type !== 'image' &&
      !isMarkdownLinkToken(token)
    ) {
      parts.push(renderInlineAstTokens(token.tokens, options));
    } else {
      parts.push(token.raw);
    }
  }
  return html`${parts}`;
}

/**
 * Render text with inline backtick code spans (`...` or ``...``) converted to
 * <code> Lit template elements using Marked's inline AST lexer.
 */
export function renderInlineCodeSpans(text: string): TemplateResult {
  if (!text) return html``;
  return renderInlineAstTokens(Lexer.lexInline(text), {includeLinks: false});
}

/**
 * Render text with markdown links ([label](url)) converted to <a> Lit template
 * elements and inline backtick code spans converted to <code> Lit template
 * elements using Marked's inline AST lexer.
 */
export function renderInlineMarkdown(text: string): TemplateResult {
  if (!text) return html``;
  return renderInlineAstTokens(Lexer.lexInline(text), {includeLinks: true});
}

/** Compute LCS-based diff between two arrays of strings (e.g. words or lines). */
export function computeSequenceDiff(
  seqA: string[],
  seqB: string[]
): InlineDiffSegment[] {
  const m = seqA.length;
  const n = seqB.length;
  // DP table for LCS lengths
  const dp: number[][] = Array.from({length: m + 1}, () =>
    new Array(n + 1).fill(0)
  );

  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      if (seqA[i] === seqB[j]) {
        dp[i + 1][j + 1] = dp[i][j] + 1;
      } else {
        dp[i + 1][j + 1] = Math.max(dp[i + 1][j], dp[i][j + 1]);
      }
    }
  }

  // Backtrack to build diff segments
  const segments: InlineDiffSegment[] = [];
  let i = m;
  let j = n;

  while (i > 0 || j > 0) {
    if (i > 0 && j > 0 && seqA[i - 1] === seqB[j - 1]) {
      segments.unshift({text: seqA[i - 1], type: 'common'});
      i--;
      j--;
    } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
      segments.unshift({text: seqB[j - 1], type: 'added'});
      j--;
    } else if (i > 0 && (j === 0 || dp[i][j - 1] < dp[i - 1][j])) {
      segments.unshift({text: seqA[i - 1], type: 'deleted'});
      i--;
    }
  }

  return segments;
}

/**
 * Tokenize a single line of code into placeholders (<...>), CLI flags,
 * identifiers, whitespace, and punctuation for within-line code diffing.
 */
export function tokenizeCodeWords(line: string): string[] {
  const codeTokenRegex =
    /<[A-Za-z0-9_.-]+>|--?[A-Za-z0-9_.-]+|\w+|\s+|[^\s\w]/g;
  return line.match(codeTokenRegex) || [];
}

/**
 * Compute the normalized token edit distance in [0.0, 1.0] between two token
 * sequences, ignoring pure-whitespace and pure-punctuation tokens so spaces and
 * punctuation do not artificially inflate similarity between unrelated
 * sentences.
 */
export function computeNormalizedEditDistance(
  seqA: string[],
  seqB: string[]
): number {
  const nonWsA = seqA.filter(t => !/^\s+$/.test(t));
  const nonWsB = seqB.filter(t => !/^\s+$/.test(t));
  if (nonWsA.length === 0 && nonWsB.length === 0) return 0;
  if (nonWsA.length === 0 || nonWsB.length === 0) return 1;

  const wordsA = nonWsA.filter(t => /\w/.test(t));
  const wordsB = nonWsB.filter(t => /\w/.test(t));
  const contentA = wordsA.length > 0 || wordsB.length > 0 ? wordsA : nonWsA;
  const contentB = wordsA.length > 0 || wordsB.length > 0 ? wordsB : nonWsB;
  if (contentA.length === 0 || contentB.length === 0) return 1;

  const diff = computeSequenceDiff(contentA, contentB);
  let commonCount = 0;
  for (const seg of diff) {
    if (seg.type === 'common') {
      commonCount++;
    }
  }
  const minLen = Math.min(contentA.length, contentB.length);
  const maxLen = Math.max(contentA.length, contentB.length);
  const diceDistance =
    1 - (2 * commonCount) / (contentA.length + contentB.length);
  const overlapDistance = 1 - commonCount / minLen;
  // If one sequence is an extension of the other (high overlap with the shorter
  // sequence, bounded length ratio, and at least 3 shared content tokens),
  // treat them as homologous so shared prefixes/clauses remain unhighlighted.
  if (commonCount >= 3 && maxLen <= minLen * 5 && overlapDistance <= 0.4) {
    return Math.min(diceDistance, overlapDistance);
  }
  return diceDistance;
}

/**
 * Coalesce fragmented inline diff segments (inspired by dandavison/delta's
 * within-line edit coalescing):
 * 1. Merge consecutive segments of the same type.
 * 2. Absorb pure-whitespace 'common' tokens sandwiched between edit segments
 *    so multi-word edits form a single continuous highlight span.
 * 3. Absorb isolated non-word punctuation at the boundary of a multi-word
 *    clause edit so trailing periods do not detach from rewritten sentences.
 */
export function coalesceInlineDiffSegments(
  segments: InlineDiffSegment[]
): InlineDiffSegment[] {
  const mergeAdjacent = (segs: InlineDiffSegment[]): InlineDiffSegment[] => {
    const merged: InlineDiffSegment[] = [];
    for (const seg of segs) {
      if (!seg.text) continue;
      const last = merged[merged.length - 1];
      if (last && last.type === seg.type) {
        last.text += seg.text;
      } else {
        merged.push({...seg});
      }
    }
    return merged;
  };

  // Group segments into alternating 'common' and edit ('deleted' + 'added') runs.
  type Run =
    | {kind: 'common'; text: string}
    | {kind: 'edit'; delText: string; addText: string};

  const buildRuns = (segs: InlineDiffSegment[]): Run[] => {
    const runs: Run[] = [];
    for (const seg of mergeAdjacent(segs)) {
      if (seg.type === 'common') {
        const last = runs[runs.length - 1];
        if (last && last.kind === 'common') {
          last.text += seg.text;
        } else {
          runs.push({kind: 'common', text: seg.text});
        }
      } else {
        let last = runs[runs.length - 1];
        if (!last || last.kind !== 'edit') {
          last = {kind: 'edit', delText: '', addText: ''};
          runs.push(last);
        }
        if (seg.type === 'deleted') {
          last.delText += seg.text;
        } else {
          last.addText += seg.text;
        }
      }
    }
    return runs;
  };

  const runs = buildRuns(segments);

  // Coalesce pure-whitespace common runs sandwiched between two edit runs
  // when both edits have deleted text or both edits have added text.
  let changed = true;
  while (changed) {
    changed = false;
    for (let i = 1; i < runs.length - 1; i++) {
      const prev = runs[i - 1];
      const curr = runs[i];
      const next = runs[i + 1];
      if (
        curr.kind === 'common' &&
        /^\s+$/.test(curr.text) &&
        prev.kind === 'edit' &&
        next.kind === 'edit'
      ) {
        const bothHaveDel = prev.delText.length > 0 && next.delText.length > 0;
        const bothHaveAdd = prev.addText.length > 0 && next.addText.length > 0;
        const prevIsPair = prev.delText.length > 0 && prev.addText.length > 0;
        const nextIsPair = next.delText.length > 0 && next.addText.length > 0;
        if (
          (bothHaveDel && !prev.addText && !next.addText) ||
          (bothHaveAdd && !prev.delText && !next.delText) ||
          (prevIsPair && nextIsPair)
        ) {
          if (prev.delText || next.delText) {
            prev.delText += curr.text + next.delText;
          }
          if (prev.addText || next.addText) {
            prev.addText += curr.text + next.addText;
          }
          runs.splice(i, 2);
          changed = true;
          break;
        }
      }
    }
  }

  // Absorb a trailing punctuation-only common run (e.g. a lone '.') when it
  // immediately follows a multi-word replacement edit that itself contains
  // sentence punctuation or whitespace.
  if (runs.length >= 2) {
    const last = runs[runs.length - 1];
    const prev = runs[runs.length - 2];
    if (
      last.kind === 'common' &&
      /^[.,;!?]+$/.test(last.text) &&
      prev.kind === 'edit' &&
      prev.delText.length > 0 &&
      prev.addText.length > 0 &&
      (/\s/.test(prev.delText) || /\s/.test(prev.addText)) &&
      prev.delText.length + prev.addText.length > 20
    ) {
      prev.delText += last.text;
      prev.addText += last.text;
      runs.pop();
    }
  }

  const out: InlineDiffSegment[] = [];
  for (const r of runs) {
    if (r.kind === 'common') {
      out.push({text: r.text, type: 'common'});
    } else {
      if (r.delText) out.push({text: r.delText, type: 'deleted'});
      if (r.addText) out.push({text: r.addText, type: 'added'});
    }
  }
  return mergeAdjacent(out);
}

/**
 * Align two lists of items using dynamic programming over normalized edit
 * distance, pairing items only when their distance is <= maxDistance.
 */
export function alignHomologousItems(
  itemsA: string[],
  itemsB: string[],
  tokenizer: (text: string) => string[] = tokenizeWords,
  maxDistance = DEFAULT_MAX_HOMOLOGOUS_DISTANCE
): Array<
  | {
      type: 'unchanged';
      textA: string;
      textB: string;
      aIdx: number;
      bIdx: number;
    }
  | {type: 'modified'; textA: string; textB: string; aIdx: number; bIdx: number}
  | {type: 'deleted'; textA: string; aIdx: number}
  | {type: 'added'; textB: string; bIdx: number}
> {
  const m = itemsA.length;
  const n = itemsB.length;
  const tokensCacheA = itemsA.map(tokenizer);
  const tokensCacheB = itemsB.map(tokenizer);

  // Score matrix: pairing (i, j) yields a positive score of (1 - distance)
  // when distance <= maxDistance.
  const pairScore: number[][] = Array.from({length: m}, (_, i) =>
    Array.from({length: n}, (__, j) => {
      if (itemsA[i] === itemsB[j]) return 2; // Strongly prefer exact matches
      const dist = computeNormalizedEditDistance(
        tokensCacheA[i],
        tokensCacheB[j]
      );
      return dist <= maxDistance ? 1 - dist : -1;
    })
  );

  const dp: number[][] = Array.from({length: m + 1}, () =>
    new Array(n + 1).fill(0)
  );

  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      let best = Math.max(dp[i][j + 1], dp[i + 1][j]);
      if (pairScore[i][j] >= 0) {
        best = Math.max(best, dp[i][j] + pairScore[i][j]);
      }
      dp[i + 1][j + 1] = best;
    }
  }

  const result: Array<
    | {
        type: 'unchanged';
        textA: string;
        textB: string;
        aIdx: number;
        bIdx: number;
      }
    | {
        type: 'modified';
        textA: string;
        textB: string;
        aIdx: number;
        bIdx: number;
      }
    | {type: 'deleted'; textA: string; aIdx: number}
    | {type: 'added'; textB: string; bIdx: number}
  > = [];

  let i = m;
  let j = n;
  while (i > 0 || j > 0) {
    if (
      i > 0 &&
      j > 0 &&
      pairScore[i - 1][j - 1] >= 0 &&
      Math.abs(dp[i][j] - (dp[i - 1][j - 1] + pairScore[i - 1][j - 1])) < 1e-9
    ) {
      const aIdx = i - 1;
      const bIdx = j - 1;
      result.unshift({
        type: itemsA[aIdx] === itemsB[bIdx] ? 'unchanged' : 'modified',
        textA: itemsA[aIdx],
        textB: itemsB[bIdx],
        aIdx,
        bIdx,
      });
      i--;
      j--;
    } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
      result.unshift({type: 'added', textB: itemsB[j - 1], bIdx: j - 1});
      j--;
    } else {
      result.unshift({type: 'deleted', textA: itemsA[i - 1], aIdx: i - 1});
      i--;
    }
  }

  return result;
}

function renderListContainer(
  listTok: Tokens.List,
  items: TemplateResult[]
): TemplateResult {
  if (!listTok.ordered) {
    return html`<ul>
      ${items}
    </ul>`;
  }
  return typeof listTok.start === 'number' && listTok.start !== 1
    ? html`<ol start=${listTok.start}>
        ${items}
      </ol>`
    : html`<ol>
        ${items}
      </ol>`;
}

/** Render a single marked block token to a Lit TemplateResult. */
export function renderTokenToHtml(token?: Token): TemplateResult {
  if (!token) return html``;
  switch (token.type) {
    case 'heading': {
      const heading = token as Tokens.Heading;
      const depth = Math.min(Math.max(heading.depth, 1), 6);
      const tag = `h${depth}` as WrapperTag;
      const content = heading.tokens
        ? renderInlineAstTokens(heading.tokens, {includeLinks: true})
        : renderInlineMarkdown(heading.text);
      return renderWrapperTag(tag, content);
    }
    case 'paragraph': {
      const para = token as Tokens.Paragraph;
      const content = para.tokens
        ? renderInlineAstTokens(para.tokens, {includeLinks: true})
        : renderInlineMarkdown(para.text);
      return html`<p>${content}</p>`;
    }
    case 'text': {
      const textTok = token as Tokens.Text;
      return textTok.tokens
        ? renderInlineAstTokens(textTok.tokens, {includeLinks: true})
        : renderInlineMarkdown(textTok.text);
    }
    case 'code': {
      const codeTok = token as Tokens.Code;
      const langClass = codeTok.lang ? `language-${codeTok.lang}` : undefined;
      return langClass
        ? html`<pre><code class=${langClass}>${codeTok.text}</code></pre>`
        : html`<pre><code>${codeTok.text}</code></pre>`;
    }
    case 'blockquote': {
      const bq = token as Tokens.Blockquote;
      const children = bq.tokens
        ? bq.tokens.map(t => renderTokenToHtml(t))
        : html`<p>${renderInlineMarkdown(bq.text.trim())}</p>`;
      return html`<blockquote>${children}</blockquote>`;
    }
    case 'list': {
      const listTok = token as Tokens.List;
      const items = listTok.items.map(item => {
        const itemContent = item.tokens
          ? item.tokens.map(t =>
              t.type === 'text'
                ? (t as Tokens.Text).tokens
                  ? renderInlineAstTokens((t as Tokens.Text).tokens!, {
                      includeLinks: true,
                    })
                  : renderInlineMarkdown((t as Tokens.Text).text)
                : renderTokenToHtml(t)
            )
          : renderInlineMarkdown(item.text);
        return html`<li>${itemContent}</li>`;
      });
      return renderListContainer(listTok, items);
    }
    case 'table': {
      const tableTok = token as Tokens.Table;
      const headerCells = tableTok.header.map(cell => {
        const content = cell.tokens
          ? renderInlineAstTokens(cell.tokens, {includeLinks: true})
          : renderInlineMarkdown(cell.text);
        return html`<th>${content}</th>`;
      });
      const bodyRows = tableTok.rows.map(row => {
        const cells = row.map(cell => {
          const content = cell.tokens
            ? renderInlineAstTokens(cell.tokens, {includeLinks: true})
            : renderInlineMarkdown(cell.text);
          return html`<td>${content}</td>`;
        });
        return html`<tr>
          ${cells}
        </tr>`;
      });
      return html`<table>
        <thead>
          <tr>
            ${headerCells}
          </tr>
        </thead>
        <tbody>
          ${bodyRows}
        </tbody>
      </table>`;
    }
    case 'hr':
      return html`<hr />`;
    case 'space':
    case 'def':
      return html``;
    default:
      return html`<p>${token.raw}</p>`;
  }
}

function renderTokensWithDiffRanges(
  tokens: Token[],
  baseOffset: number,
  isEditedAt: boolean[],
  highlightTag: 'del' | 'ins',
  highlightClass: string
): TemplateResult {
  const result: Array<TemplateResult | string> = [];
  let activeHighlight: Array<TemplateResult | string> = [];
  const flushHighlight = () => {
    if (activeHighlight.length > 0) {
      result.push(
        renderHighlightTag(
          highlightTag,
          highlightClass,
          html`${activeHighlight}`
        )
      );
      activeHighlight = [];
    }
  };

  let offset = baseOffset;
  for (const token of tokens) {
    const tokStart = offset;
    const tokEnd = offset + token.raw.length;
    offset = tokEnd;

    let anyEdited = false;
    let allEdited = token.raw.length > 0;
    for (let p = tokStart; p < tokEnd; p++) {
      if (isEditedAt[p]) {
        anyEdited = true;
      } else {
        allEdited = false;
      }
    }

    if (allEdited || (anyEdited && token.type === 'escape')) {
      activeHighlight.push(
        renderInlineAstTokens([token], {includeLinks: true})
      );
    } else if (!anyEdited) {
      flushHighlight();
      result.push(renderInlineAstTokens([token], {includeLinks: true}));
    } else if (isInlineContainerToken(token)) {
      const {openDelim, closeDelim} = getContainerDelimiters(token);
      const innerStart = tokStart + openDelim.length;
      const innerEnd = tokEnd - closeDelim.length;
      let innerAnyEdited = false;
      for (let p = innerStart; p < innerEnd; p++) {
        if (isEditedAt[p]) {
          innerAnyEdited = true;
          break;
        }
      }
      if (!innerAnyEdited) {
        activeHighlight.push(
          renderInlineAstTokens([token], {includeLinks: true})
        );
      } else {
        flushHighlight();
        const innerTemplate = renderTokensWithDiffRanges(
          token.tokens,
          innerStart,
          isEditedAt,
          highlightTag,
          highlightClass
        );
        result.push(renderInlineContainerTag(token.type, innerTemplate));
      }
    } else {
      let runStart = tokStart;
      while (runStart < tokEnd) {
        const runEdited = isEditedAt[runStart];
        let runEnd = runStart + 1;
        while (runEnd < tokEnd && isEditedAt[runEnd] === runEdited) {
          runEnd++;
        }
        const sliceText = token.raw.slice(
          runStart - tokStart,
          runEnd - tokStart
        );
        if (runEdited) {
          activeHighlight.push(sliceText);
        } else {
          flushHighlight();
          result.push(sliceText);
        }
        runStart = runEnd;
      }
    }
  }
  flushHighlight();
  return html`${result}`;
}

function renderSideInlineDiff(
  fullText: string,
  segments: InlineDiffSegment[],
  editType: 'deleted' | 'added',
  highlightTag: 'del' | 'ins',
  highlightClass: string
): TemplateResult {
  if (!fullText) return html``;
  const isEditedAt = new Array<boolean>(fullText.length).fill(false);
  let pos = 0;
  for (const seg of segments) {
    if (seg.type === 'common' || seg.type === editType) {
      if (seg.type === editType) {
        for (let i = 0; i < seg.text.length && pos + i < fullText.length; i++) {
          isEditedAt[pos + i] = true;
        }
      }
      pos += seg.text.length;
    }
  }
  return renderTokensWithDiffRanges(
    Lexer.lexInline(fullText),
    0,
    isEditedAt,
    highlightTag,
    highlightClass
  );
}

function renderInlineTextDiffContent(
  textA: string,
  textB: string
): {leftContent: TemplateResult; rightContent: TemplateResult} {
  const wordsA = tokenizeWords(textA);
  const wordsB = tokenizeWords(textB);
  const distance = computeNormalizedEditDistance(wordsA, wordsB);

  let mergedSegments: InlineDiffSegment[];
  if (distance > DEFAULT_MAX_HOMOLOGOUS_DISTANCE) {
    // Non-homologous lines/blocks: highlight as whole replacements rather than
    // producing noisy "ransom-note" diffs across incidental stop words.
    mergedSegments = [];
    if (textA) mergedSegments.push({text: textA, type: 'deleted'});
    if (textB) mergedSegments.push({text: textB, type: 'added'});
  } else {
    const diff = computeSequenceDiff(wordsA, wordsB);
    mergedSegments = coalesceInlineDiffSegments(diff);
  }

  const leftContent = renderSideInlineDiff(
    textA,
    mergedSegments,
    'deleted',
    'del',
    'diff-highlight-del'
  );
  const rightContent = renderSideInlineDiff(
    textB,
    mergedSegments,
    'added',
    'ins',
    'diff-highlight-add'
  );

  return {leftContent, rightContent};
}

/** Render an inline diff for modified text in headings or paragraphs. */
export function renderInlineTextDiff(
  textA: string,
  textB: string,
  wrapperTag: WrapperTag = 'p',
  rightWrapperTag: WrapperTag = wrapperTag
): {leftHtml: TemplateResult; rightHtml: TemplateResult} {
  const {leftContent, rightContent} = renderInlineTextDiffContent(textA, textB);
  return {
    leftHtml: renderWrapperTag(wrapperTag, leftContent),
    rightHtml: renderWrapperTag(rightWrapperTag, rightContent),
  };
}

/**
 * Render a modified code block with two-tier dandavison/delta-style highlights:
 * homologous modified lines get a subtle full-line background plus within-line
 * token emphasis on the specific tokens that changed.
 */
export function renderCodeBlockDiff(
  tokenA: Tokens.Code,
  tokenB: Tokens.Code
): {leftHtml: TemplateResult; rightHtml: TemplateResult} {
  const linesA = tokenA.text.split('\n');
  const linesB = tokenB.text.split('\n');
  const aligned = alignHomologousItems(
    linesA,
    linesB,
    tokenizeCodeWords,
    DEFAULT_MAX_HOMOLOGOUS_DISTANCE
  );

  const leftLineEntries: Array<TemplateResult | string> = [];
  const rightLineEntries: Array<TemplateResult | string> = [];

  for (const item of aligned) {
    if (item.type === 'unchanged') {
      leftLineEntries.push(item.textA);
      rightLineEntries.push(item.textA);
    } else if (item.type === 'deleted') {
      leftLineEntries.push(
        html`<span class="diff-highlight-del">${item.textA}</span>`
      );
    } else if (item.type === 'added') {
      rightLineEntries.push(
        html`<span class="diff-highlight-add">${item.textB}</span>`
      );
    } else {
      const wordsA = tokenizeCodeWords(item.textA);
      const wordsB = tokenizeCodeWords(item.textB);
      const rawDiff = computeSequenceDiff(wordsA, wordsB);
      const commonNonWsCount = rawDiff.filter(
        s => s.type === 'common' && !/^\s+$/.test(s.text)
      ).length;

      if (commonNonWsCount < 2) {
        leftLineEntries.push(
          html`<span class="diff-highlight-del">${item.textA}</span>`
        );
        rightLineEntries.push(
          html`<span class="diff-highlight-add">${item.textB}</span>`
        );
      } else {
        const coalesced = coalesceInlineDiffSegments(rawDiff);
        const leftParts: Array<TemplateResult | string> = [];
        const rightParts: Array<TemplateResult | string> = [];
        for (const seg of coalesced) {
          if (seg.type === 'common') {
            leftParts.push(seg.text);
            rightParts.push(seg.text);
          } else if (seg.type === 'deleted') {
            leftParts.push(
              html`<del class="diff-highlight-del">${seg.text}</del>`
            );
          } else if (seg.type === 'added') {
            rightParts.push(
              html`<ins class="diff-highlight-add">${seg.text}</ins>`
            );
          }
        }
        leftLineEntries.push(
          html`<span class="diff-code-line-del">${leftParts}</span>`
        );
        rightLineEntries.push(
          html`<span class="diff-code-line-add">${rightParts}</span>`
        );
      }
    }
  }

  const joinLinesWithNewline = (
    entries: Array<TemplateResult | string>
  ): Array<TemplateResult | string> => {
    const out: Array<TemplateResult | string> = [];
    for (let i = 0; i < entries.length; i++) {
      if (i > 0) out.push('\n');
      out.push(entries[i]);
    }
    return out;
  };

  const leftCodeContent = joinLinesWithNewline(leftLineEntries);
  const rightCodeContent = joinLinesWithNewline(rightLineEntries);
  const langA = tokenA.lang ? `language-${tokenA.lang}` : undefined;
  const langB = tokenB.lang ? `language-${tokenB.lang}` : undefined;

  return {
    leftHtml: langA
      ? html`<pre><code class=${langA}>${leftCodeContent}</code></pre>`
      : html`<pre><code>${leftCodeContent}</code></pre>`,
    rightHtml: langB
      ? html`<pre><code class=${langB}>${rightCodeContent}</code></pre>`
      : html`<pre><code>${rightCodeContent}</code></pre>`,
  };
}

function splitListItemTokens(item: Tokens.ListItem): {
  headText: string;
  sublists: Tokens.List[];
  otherBlocks: Token[];
} {
  if (!item.tokens || item.tokens.length === 0) {
    return {headText: item.text, sublists: [], otherBlocks: []};
  }
  const headParts: string[] = [];
  const sublists: Tokens.List[] = [];
  const otherBlocks: Token[] = [];
  for (const t of item.tokens) {
    if (t.type === 'text' || t.type === 'paragraph') {
      headParts.push((t as Tokens.Text | Tokens.Paragraph).text);
    } else if (t.type === 'list') {
      sublists.push(t as Tokens.List);
    } else if (t.type !== 'space') {
      otherBlocks.push(t);
    }
  }
  return {
    headText: headParts.join('\n'),
    sublists,
    otherBlocks,
  };
}

/**
 * Render a modified markdown list (<ul> or <ol>) by aligning homologous list
 * items and highlighting within-item word/code/link diffs as well as added or
 * deleted items. Emits placeholder <li> elements on the opposing side so
 * side-by-side alignment and <ol> numbering stay in sync.
 */
export function renderListDiff(
  tokenA: Tokens.List,
  tokenB: Tokens.List
): {leftHtml: TemplateResult; rightHtml: TemplateResult} {
  const splitItemsA = tokenA.items.map(splitListItemTokens);
  const splitItemsB = tokenB.items.map(splitListItemTokens);
  const itemsA = splitItemsA.map(
    (s, idx) => s.headText || tokenA.items[idx].text
  );
  const itemsB = splitItemsB.map(
    (s, idx) => s.headText || tokenB.items[idx].text
  );
  const aligned = alignHomologousItems(
    itemsA,
    itemsB,
    tokenizeWords,
    DEFAULT_MAX_HOMOLOGOUS_DISTANCE
  );

  const leftItems: TemplateResult[] = [];
  const rightItems: TemplateResult[] = [];

  for (const item of aligned) {
    if (item.type === 'unchanged' || item.type === 'modified') {
      const splitA = splitItemsA[item.aIdx];
      const splitB = splitItemsB[item.bIdx];
      let leftHead: TemplateResult;
      let rightHead: TemplateResult;
      if (splitA.headText === splitB.headText) {
        leftHead = renderInlineMarkdown(splitA.headText);
        rightHead = leftHead;
      } else {
        const diffContent = renderInlineTextDiffContent(
          splitA.headText,
          splitB.headText
        );
        leftHead = diffContent.leftContent;
        rightHead = diffContent.rightContent;
      }

      const leftSublists: TemplateResult[] = [];
      const rightSublists: TemplateResult[] = [];
      const maxSub = Math.max(splitA.sublists.length, splitB.sublists.length);
      for (let s = 0; s < maxSub; s++) {
        const subA = splitA.sublists[s];
        const subB = splitB.sublists[s];
        if (subA && subB) {
          const subDiff = renderListDiff(subA, subB);
          leftSublists.push(subDiff.leftHtml);
          rightSublists.push(subDiff.rightHtml);
        } else if (subA) {
          leftSublists.push(
            renderListDiff(subA, {...subA, items: []}).leftHtml
          );
        } else if (subB) {
          rightSublists.push(
            renderListDiff({...subB, items: []}, subB).rightHtml
          );
        }
      }

      const leftOther = splitA.otherBlocks.map(t => renderTokenToHtml(t));
      const rightOther = splitB.otherBlocks.map(t => renderTokenToHtml(t));
      leftItems.push(html`<li>${leftHead}${leftOther}${leftSublists}</li>`);
      rightItems.push(html`<li>${rightHead}${rightOther}${rightSublists}</li>`);
    } else if (item.type === 'deleted') {
      const splitA = splitItemsA[item.aIdx];
      const sublists = splitA.sublists.map(
        sub => renderListDiff(sub, {...sub, items: []}).leftHtml
      );
      const other = splitA.otherBlocks.map(t => renderTokenToHtml(t));
      leftItems.push(
        html`<li class="diff-list-item-del">
          <del class="diff-highlight-del"
            >${renderInlineMarkdown(splitA.headText)}</del
          >${other}${sublists}
        </li>`
      );
      rightItems.push(
        html`<li class="diff-list-item-placeholder" aria-hidden="true"></li>`
      );
    } else if (item.type === 'added') {
      const splitB = splitItemsB[item.bIdx];
      const sublists = splitB.sublists.map(
        sub => renderListDiff({...sub, items: []}, sub).rightHtml
      );
      const other = splitB.otherBlocks.map(t => renderTokenToHtml(t));
      leftItems.push(
        html`<li class="diff-list-item-placeholder" aria-hidden="true"></li>`
      );
      rightItems.push(
        html`<li class="diff-list-item-add">
          <ins class="diff-highlight-add"
            >${renderInlineMarkdown(splitB.headText)}</ins
          >${other}${sublists}
        </li>`
      );
    }
  }

  return {
    leftHtml: renderListContainer(tokenA, leftItems),
    rightHtml: renderListContainer(tokenB, rightItems),
  };
}

/** Render a modified blockquote with inline word/code/link diff highlights. */
export function renderBlockquoteDiff(
  tokenA: Tokens.Blockquote,
  tokenB: Tokens.Blockquote
): {leftHtml: TemplateResult; rightHtml: TemplateResult} {
  const childTokensA = (
    tokenA.tokens && tokenA.tokens.length > 0
      ? tokenA.tokens
      : parseMarkdownBlocks(tokenA.text)
  ).filter(t => t.type !== 'space') as MarkdownToken[];
  const childTokensB = (
    tokenB.tokens && tokenB.tokens.length > 0
      ? tokenB.tokens
      : parseMarkdownBlocks(tokenB.text)
  ).filter(t => t.type !== 'space') as MarkdownToken[];

  if (
    childTokensA.length <= 1 &&
    childTokensB.length <= 1 &&
    (childTokensA[0]?.type ?? 'paragraph') === 'paragraph' &&
    (childTokensB[0]?.type ?? 'paragraph') === 'paragraph'
  ) {
    const {leftHtml, rightHtml} = renderInlineTextDiff(
      tokenA.text.trim(),
      tokenB.text.trim(),
      'p'
    );
    return {
      leftHtml: html`<blockquote>${leftHtml}</blockquote>`,
      rightHtml: html`<blockquote>${rightHtml}</blockquote>`,
    };
  }

  const alignedChildren = alignMarkdownTokens(childTokensA, childTokensB);
  const leftBlocks: TemplateResult[] = [];
  const rightBlocks: TemplateResult[] = [];
  for (const row of alignedChildren) {
    if (row.status === 'unchanged' || row.status === 'modified') {
      if (row.leftHtml) leftBlocks.push(row.leftHtml);
      if (row.rightHtml) rightBlocks.push(row.rightHtml);
    } else if (row.status === 'deleted' && row.leftToken) {
      if (row.leftToken.type === 'paragraph') {
        leftBlocks.push(
          renderInlineTextDiff(
            (row.leftToken as Tokens.Paragraph).text,
            '',
            'p'
          ).leftHtml
        );
      } else if (row.leftHtml) {
        leftBlocks.push(
          html`<del class="diff-highlight-del">${row.leftHtml}</del>`
        );
      }
    } else if (row.status === 'added' && row.rightToken) {
      if (row.rightToken.type === 'paragraph') {
        rightBlocks.push(
          renderInlineTextDiff(
            '',
            (row.rightToken as Tokens.Paragraph).text,
            'p'
          ).rightHtml
        );
      } else if (row.rightHtml) {
        rightBlocks.push(
          html`<ins class="diff-highlight-add">${row.rightHtml}</ins>`
        );
      }
    }
  }

  return {
    leftHtml: html`<blockquote>${leftBlocks}</blockquote>`,
    rightHtml: html`<blockquote>${rightBlocks}</blockquote>`,
  };
}

/**
 * Render a modified markdown table by aligning homologous rows and performing
 * cell-by-cell inline diffs on modified header and body cells, emitting
 * placeholder cells and rows on the opposing side when columns or rows are
 * added or deleted.
 */
export function renderTableDiff(
  tokenA: Tokens.Table,
  tokenB: Tokens.Table
): {leftHtml: TemplateResult; rightHtml: TemplateResult} {
  const colCount = Math.max(
    tokenA.header.length,
    tokenB.header.length,
    ...tokenA.rows.map(r => r.length),
    ...tokenB.rows.map(r => r.length)
  );
  const leftHeaderCells: TemplateResult[] = [];
  const rightHeaderCells: TemplateResult[] = [];

  for (let c = 0; c < colCount; c++) {
    const cellA = tokenA.header[c]?.text;
    const cellB = tokenB.header[c]?.text;
    if (cellA !== undefined && cellB !== undefined) {
      if (cellA === cellB) {
        const th = html`<th>${renderInlineMarkdown(cellA)}</th>`;
        leftHeaderCells.push(th);
        rightHeaderCells.push(th);
      } else {
        const {leftHtml, rightHtml} = renderInlineTextDiff(cellA, cellB, 'th');
        leftHeaderCells.push(leftHtml);
        rightHeaderCells.push(rightHtml);
      }
    } else if (cellA !== undefined) {
      leftHeaderCells.push(
        html`<th>
          <del class="diff-highlight-del">${renderInlineMarkdown(cellA)}</del>
        </th>`
      );
      rightHeaderCells.push(
        html`<th class="diff-table-cell-placeholder" aria-hidden="true"></th>`
      );
    } else if (cellB !== undefined) {
      leftHeaderCells.push(
        html`<th class="diff-table-cell-placeholder" aria-hidden="true"></th>`
      );
      rightHeaderCells.push(
        html`<th>
          <ins class="diff-highlight-add">${renderInlineMarkdown(cellB)}</ins>
        </th>`
      );
    } else {
      leftHeaderCells.push(
        html`<th class="diff-table-cell-placeholder" aria-hidden="true"></th>`
      );
      rightHeaderCells.push(
        html`<th class="diff-table-cell-placeholder" aria-hidden="true"></th>`
      );
    }
  }

  const rowsTextA = tokenA.rows.map(r => r.map(c => c.text).join(' '));
  const rowsTextB = tokenB.rows.map(r => r.map(c => c.text).join(' '));
  const alignedRows = alignHomologousItems(
    rowsTextA,
    rowsTextB,
    tokenizeWords,
    DEFAULT_MAX_HOMOLOGOUS_DISTANCE
  );

  const leftBodyRows: TemplateResult[] = [];
  const rightBodyRows: TemplateResult[] = [];

  for (const row of alignedRows) {
    if (row.type === 'unchanged') {
      const trLeft: TemplateResult[] = [];
      const trRight: TemplateResult[] = [];
      const cellsA = tokenA.rows[row.aIdx];
      const cellsB = tokenB.rows[row.bIdx];
      for (let c = 0; c < colCount; c++) {
        const cellA = cellsA[c]?.text;
        const cellB = cellsB[c]?.text;
        trLeft.push(
          cellA !== undefined
            ? html`<td>${renderInlineMarkdown(cellA)}</td>`
            : html`<td
                class="diff-table-cell-placeholder"
                aria-hidden="true"
              ></td>`
        );
        trRight.push(
          cellB !== undefined
            ? html`<td>${renderInlineMarkdown(cellB)}</td>`
            : html`<td
                class="diff-table-cell-placeholder"
                aria-hidden="true"
              ></td>`
        );
      }
      leftBodyRows.push(
        html`<tr>
          ${trLeft}
        </tr>`
      );
      rightBodyRows.push(
        html`<tr>
          ${trRight}
        </tr>`
      );
    } else if (row.type === 'modified') {
      const cellsA = tokenA.rows[row.aIdx];
      const cellsB = tokenB.rows[row.bIdx];
      const trLeft: TemplateResult[] = [];
      const trRight: TemplateResult[] = [];
      for (let c = 0; c < colCount; c++) {
        const textA = cellsA[c]?.text;
        const textB = cellsB[c]?.text;
        if (textA !== undefined && textB !== undefined) {
          if (textA === textB) {
            const td = html`<td>${renderInlineMarkdown(textA)}</td>`;
            trLeft.push(td);
            trRight.push(td);
          } else {
            const {leftHtml, rightHtml} = renderInlineTextDiff(
              textA,
              textB,
              'td'
            );
            trLeft.push(leftHtml);
            trRight.push(rightHtml);
          }
        } else if (textA !== undefined) {
          trLeft.push(
            html`<td>
              <del class="diff-highlight-del"
                >${renderInlineMarkdown(textA)}</del
              >
            </td>`
          );
          trRight.push(
            html`<td
              class="diff-table-cell-placeholder"
              aria-hidden="true"
            ></td>`
          );
        } else if (textB !== undefined) {
          trLeft.push(
            html`<td
              class="diff-table-cell-placeholder"
              aria-hidden="true"
            ></td>`
          );
          trRight.push(
            html`<td>
              <ins class="diff-highlight-add"
                >${renderInlineMarkdown(textB)}</ins
              >
            </td>`
          );
        } else {
          trLeft.push(
            html`<td
              class="diff-table-cell-placeholder"
              aria-hidden="true"
            ></td>`
          );
          trRight.push(
            html`<td
              class="diff-table-cell-placeholder"
              aria-hidden="true"
            ></td>`
          );
        }
      }
      leftBodyRows.push(
        html`<tr>
          ${trLeft}
        </tr>`
      );
      rightBodyRows.push(
        html`<tr>
          ${trRight}
        </tr>`
      );
    } else if (row.type === 'deleted') {
      const cellsA = tokenA.rows[row.aIdx];
      const trLeft: TemplateResult[] = [];
      const trRight: TemplateResult[] = [];
      for (let c = 0; c < colCount; c++) {
        const cellA = cellsA[c]?.text;
        trLeft.push(
          cellA !== undefined
            ? html`<td>
                <del class="diff-highlight-del"
                  >${renderInlineMarkdown(cellA)}</del
                >
              </td>`
            : html`<td
                class="diff-table-cell-placeholder"
                aria-hidden="true"
              ></td>`
        );
        trRight.push(
          html`<td class="diff-table-cell-placeholder" aria-hidden="true"></td>`
        );
      }
      leftBodyRows.push(
        html`<tr class="diff-table-row-del">
          ${trLeft}
        </tr>`
      );
      rightBodyRows.push(
        html`<tr class="diff-table-row-placeholder" aria-hidden="true">
          ${trRight}
        </tr>`
      );
    } else if (row.type === 'added') {
      const cellsB = tokenB.rows[row.bIdx];
      const trLeft: TemplateResult[] = [];
      const trRight: TemplateResult[] = [];
      for (let c = 0; c < colCount; c++) {
        const cellB = cellsB[c]?.text;
        trLeft.push(
          html`<td class="diff-table-cell-placeholder" aria-hidden="true"></td>`
        );
        trRight.push(
          cellB !== undefined
            ? html`<td>
                <ins class="diff-highlight-add"
                  >${renderInlineMarkdown(cellB)}</ins
                >
              </td>`
            : html`<td
                class="diff-table-cell-placeholder"
                aria-hidden="true"
              ></td>`
        );
      }
      leftBodyRows.push(
        html`<tr class="diff-table-row-placeholder" aria-hidden="true">
          ${trLeft}
        </tr>`
      );
      rightBodyRows.push(
        html`<tr class="diff-table-row-add">
          ${trRight}
        </tr>`
      );
    }
  }

  return {
    leftHtml: html`<table>
      <thead>
        <tr>
          ${leftHeaderCells}
        </tr>
      </thead>
      <tbody>
        ${leftBodyRows}
      </tbody>
    </table>`,
    rightHtml: html`<table>
      <thead>
        <tr>
          ${rightHeaderCells}
        </tr>
      </thead>
      <tbody>
        ${rightBodyRows}
      </tbody>
    </table>`,
  };
}

/**
 * Align base (A) and revision (B) markdown block tokens into rows.
 * Matches exact blocks as anchors, pairs modified blocks of compatible types,
 * and leaves unmatched blocks as added or deleted with empty partner cells.
 */
export function alignMarkdownTokens(
  tokensA: MarkdownToken[],
  tokensB: MarkdownToken[]
): AlignedDiffRow[] {
  // Filter out whitespace-only 'space' tokens between blocks
  const blocksA = tokensA.filter(t => t.type !== 'space');
  const blocksB = tokensB.filter(t => t.type !== 'space');

  const m = blocksA.length;
  const n = blocksB.length;

  // DP table to find LCS of exact matches
  const dp: number[][] = Array.from({length: m + 1}, () =>
    new Array(n + 1).fill(0)
  );

  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      if (blocksA[i].raw === blocksB[j].raw) {
        dp[i + 1][j + 1] = dp[i][j] + 1;
      } else {
        dp[i + 1][j + 1] = Math.max(dp[i + 1][j], dp[i][j + 1]);
      }
    }
  }

  // Backtrack to extract exact match pairs
  const anchorPairs: {aIdx: number; bIdx: number}[] = [];
  let i = m;
  let j = n;
  while (i > 0 && j > 0) {
    if (blocksA[i - 1].raw === blocksB[j - 1].raw) {
      anchorPairs.unshift({aIdx: i - 1, bIdx: j - 1});
      i--;
      j--;
    } else if (dp[i][j - 1] >= dp[i - 1][j]) {
      j--;
    } else {
      i--;
    }
  }

  const rows: AlignedDiffRow[] = [];
  let lastA = 0;
  let lastB = 0;

  function renderPairedBlocks(
    tokA: MarkdownToken,
    tokB: MarkdownToken
  ): {leftHtml: TemplateResult; rightHtml: TemplateResult} {
    if (tokA.type === 'code' && tokB.type === 'code') {
      return renderCodeBlockDiff(tokA as Tokens.Code, tokB as Tokens.Code);
    }
    if (tokA.type === 'heading' && tokB.type === 'heading') {
      const depthA = Math.min(Math.max((tokA as Tokens.Heading).depth, 1), 6);
      const depthB = Math.min(Math.max((tokB as Tokens.Heading).depth, 1), 6);
      return renderInlineTextDiff(
        tokA.text,
        tokB.text,
        `h${depthA}` as WrapperTag,
        `h${depthB}` as WrapperTag
      );
    }
    if (tokA.type === 'paragraph' && tokB.type === 'paragraph') {
      return renderInlineTextDiff(tokA.text, tokB.text, 'p');
    }
    if (tokA.type === 'list' && tokB.type === 'list') {
      return renderListDiff(tokA as Tokens.List, tokB as Tokens.List);
    }
    if (tokA.type === 'blockquote' && tokB.type === 'blockquote') {
      return renderBlockquoteDiff(
        tokA as Tokens.Blockquote,
        tokB as Tokens.Blockquote
      );
    }
    if (tokA.type === 'table' && tokB.type === 'table') {
      return renderTableDiff(tokA as Tokens.Table, tokB as Tokens.Table);
    }
    return {
      leftHtml: renderTokenToHtml(tokA),
      rightHtml: renderTokenToHtml(tokB),
    };
  }

  function processInterval(endA: number, endB: number) {
    const unalignedA = blocksA.slice(lastA, endA);
    const unalignedB = blocksB.slice(lastB, endB);
    const uA = unalignedA.length;
    const uB = unalignedB.length;
    if (uA === 0 && uB === 0) return;

    const tokenizeBlock = (t: MarkdownToken): string[] =>
      t.type === 'code'
        ? tokenizeCodeWords((t as Tokens.Code).text)
        : tokenizeWords(t.raw);
    const wordsCacheA = unalignedA.map(tokenizeBlock);
    const wordsCacheB = unalignedB.map(tokenizeBlock);

    // Score compatible block pairs by homologous similarity so inserted or
    // deleted blocks do not shift adjacent modified blocks out of alignment.
    const pairScore: number[][] = Array.from({length: uA}, (_, a) =>
      Array.from({length: uB}, (__, b) => {
        if (unalignedA[a].type !== unalignedB[b].type) return -1;
        const dist = computeNormalizedEditDistance(
          wordsCacheA[a],
          wordsCacheB[b]
        );
        if (dist <= DEFAULT_MAX_HOMOLOGOUS_DISTANCE) {
          return 1 + (1 - dist);
        }
        return uA === 1 && uB === 1 ? 0.01 + 0.1 * (1 - dist) : -1;
      })
    );

    const subDp: number[][] = Array.from({length: uA + 1}, () =>
      new Array(uB + 1).fill(0)
    );
    for (let a = 0; a < uA; a++) {
      for (let b = 0; b < uB; b++) {
        let best = Math.max(subDp[a][b + 1], subDp[a + 1][b]);
        if (pairScore[a][b] >= 0) {
          best = Math.max(best, subDp[a][b] + pairScore[a][b]);
        }
        subDp[a + 1][b + 1] = best;
      }
    }

    const intervalRows: AlignedDiffRow[] = [];
    let a = uA;
    let b = uB;
    while (a > 0 || b > 0) {
      if (
        a > 0 &&
        b > 0 &&
        pairScore[a - 1][b - 1] >= 0 &&
        Math.abs(
          subDp[a][b] - (subDp[a - 1][b - 1] + pairScore[a - 1][b - 1])
        ) < 1e-9
      ) {
        const tokA = unalignedA[a - 1];
        const tokB = unalignedB[b - 1];
        const {leftHtml, rightHtml} = renderPairedBlocks(tokA, tokB);
        intervalRows.unshift({
          status: 'modified',
          leftToken: tokA,
          rightToken: tokB,
          leftHtml,
          rightHtml,
          leftStartLine: tokA.startLine,
          leftEndLine: tokA.endLine,
          rightStartLine: tokB.startLine,
          rightEndLine: tokB.endLine,
        });
        a--;
        b--;
      } else if (b > 0 && (a === 0 || subDp[a][b - 1] >= subDp[a - 1][b])) {
        const tokB = unalignedB[b - 1];
        intervalRows.unshift({
          status: 'added',
          rightToken: tokB,
          rightHtml: renderTokenToHtml(tokB),
          rightStartLine: tokB.startLine,
          rightEndLine: tokB.endLine,
        });
        b--;
      } else {
        const tokA = unalignedA[a - 1];
        intervalRows.unshift({
          status: 'deleted',
          leftToken: tokA,
          leftHtml: renderTokenToHtml(tokA),
          leftStartLine: tokA.startLine,
          leftEndLine: tokA.endLine,
        });
        a--;
      }
    }

    rows.push(...intervalRows);
  }

  // Interleave intervals between anchor pairs
  for (const anchor of anchorPairs) {
    processInterval(anchor.aIdx, anchor.bIdx);
    const tokA = blocksA[anchor.aIdx];
    const tokB = blocksB[anchor.bIdx];
    const htmlA = renderTokenToHtml(tokA);
    const htmlB = renderTokenToHtml(tokB);
    rows.push({
      status: 'unchanged',
      leftToken: tokA,
      rightToken: tokB,
      leftHtml: htmlA,
      rightHtml: htmlB,
      leftStartLine: tokA.startLine,
      leftEndLine: tokA.endLine,
      rightStartLine: tokB.startLine,
      rightEndLine: tokB.endLine,
    });
    lastA = anchor.aIdx + 1;
    lastB = anchor.bIdx + 1;
  }

  // Trailing interval
  processInterval(m, n);

  return rows;
}

/** Determine which side of the diff (LEFT or RIGHT) a comment thread belongs to. */
export function getThreadDiffSide(
  thread: CommentThread,
  patchRange?: PatchRange
): Side {
  if (!patchRange) {
    return thread.commentSide === CommentSide.PARENT ? Side.LEFT : Side.RIGHT;
  }
  const commentProps = {
    patch_set: thread.patchNum,
    side: thread.commentSide,
    parent: thread.mergeParentNum,
  };
  if (isInBaseOfPatchRange(commentProps, patchRange)) {
    return Side.LEFT;
  }
  return Side.RIGHT;
}

/**
 * Assigns comment threads to their corresponding markdown diff rows based on line
 * numbers and diff side. File-level comments (or threads without line numbers) are
 * grouped separately.
 */
export function attachThreadsToRows(
  rows: AlignedDiffRow[],
  threads: CommentThread[] = [],
  patchRange?: PatchRange
): {
  rowsWithThreads: AlignedDiffRowWithThreads[];
  fileLevelThreads: CommentThread[];
} {
  const rowsWithThreads: AlignedDiffRowWithThreads[] = rows.map(r => {
    return {
      ...r,
      leftThreads: [],
      rightThreads: [],
    };
  });

  const fileLevelThreads: CommentThread[] = [];

  if (rowsWithThreads.length === 0) {
    return {
      rowsWithThreads,
      fileLevelThreads: [...threads],
    };
  }

  for (const thread of threads) {
    const line = thread.line;
    if (line === undefined || line === 'FILE') {
      fileLevelThreads.push(thread);
      continue;
    }

    const lineNum = typeof line === 'number' ? line : Number(line);
    if (isNaN(lineNum)) {
      fileLevelThreads.push(thread);
      continue;
    }

    const side = getThreadDiffSide(thread, patchRange);

    if (side === Side.LEFT) {
      const leftRows = rowsWithThreads.filter(
        r => r.leftStartLine !== undefined
      );
      if (leftRows.length === 0) {
        rowsWithThreads[0].leftThreads.push(thread);
        continue;
      }

      const exactRow = leftRows.find(
        r => lineNum >= r.leftStartLine! && lineNum <= r.leftEndLine!
      );
      if (exactRow) {
        exactRow.leftThreads.push(thread);
        continue;
      }

      if (lineNum < leftRows[0].leftStartLine!) {
        leftRows[0].leftThreads.push(thread);
        continue;
      }

      let targetRow = leftRows[leftRows.length - 1];
      for (let i = 0; i < leftRows.length - 1; i++) {
        if (
          lineNum > leftRows[i].leftEndLine! &&
          lineNum < leftRows[i + 1].leftStartLine!
        ) {
          targetRow = leftRows[i];
          break;
        }
      }
      targetRow.leftThreads.push(thread);
    } else {
      const rightRows = rowsWithThreads.filter(
        r => r.rightStartLine !== undefined
      );
      if (rightRows.length === 0) {
        rowsWithThreads[0].rightThreads.push(thread);
        continue;
      }

      const exactRow = rightRows.find(
        r => lineNum >= r.rightStartLine! && lineNum <= r.rightEndLine!
      );
      if (exactRow) {
        exactRow.rightThreads.push(thread);
        continue;
      }

      if (lineNum < rightRows[0].rightStartLine!) {
        rightRows[0].rightThreads.push(thread);
        continue;
      }

      let targetRow = rightRows[rightRows.length - 1];
      for (let i = 0; i < rightRows.length - 1; i++) {
        if (
          lineNum > rightRows[i].rightEndLine! &&
          lineNum < rightRows[i + 1].rightStartLine!
        ) {
          targetRow = rightRows[i];
          break;
        }
      }
      targetRow.rightThreads.push(thread);
    }
  }

  return {rowsWithThreads, fileLevelThreads};
}
