import { type Hunk, structuredPatch } from 'diff'

const CONTEXT_LINES = 3

// For some reason, & confuses the diff library, so we replace it with a token,
// then substitute it back in after the diff is computed.
const AMPERSAND_TOKEN = '<<:AMPERSAND_TOKEN:>>'

const DOLLAR_TOKEN = '<<:DOLLAR_TOKEN:>>'

export function getPatch({
  filePath,
  fileContents,
  oldStr,
  newStr,
}: {
  filePath: string
  fileContents: string
  oldStr: string
  newStr: string
}): Hunk[] {
  return structuredPatch(
    filePath,
    filePath,
    fileContents.replaceAll('&', AMPERSAND_TOKEN).replaceAll('$', DOLLAR_TOKEN),
    fileContents
      .replaceAll('&', AMPERSAND_TOKEN)
      .replaceAll('$', DOLLAR_TOKEN)
      .replace(
        oldStr.replaceAll('&', AMPERSAND_TOKEN).replaceAll('$', DOLLAR_TOKEN),
        newStr.replaceAll('&', AMPERSAND_TOKEN).replaceAll('$', DOLLAR_TOKEN),
      ),
    undefined,
    undefined,
    { context: CONTEXT_LINES },
  ).hunks.map(_ => ({
    ..._,
    lines: _.lines.map(_ =>
      _.replaceAll(AMPERSAND_TOKEN, '&').replaceAll(DOLLAR_TOKEN, '$'),
    ),
  }))
}
