///|
fn optional_name(value : String?) -> String {
  match value {
    Some(name) => "`\{name}`"
    None => "—"
  }
}

///|
fn change_marker(change : ApiChange) -> String {
  if change.change_kind is Added {
    "ADD"
  } else if change.safely_shimmable {
    "SHIM"
  } else {
    "BLOCK"
  }
}

///|
/// Renders a human-readable Markdown migration report.
pub fn render_markdown(
  plan : MigrationPlan,
  old_name : StringView,
  new_name : StringView,
) -> String {
  let builder = StringBuilder()
  builder.write_string("# MoonShim migration report\n\n")
  builder.write_string("- Old interface: `\{old_name}`\n")
  builder.write_string("- New interface: `\{new_name}`\n")
  builder.write_string("- Changes: \{plan.changes.length()}\n")
  builder.write_string("- Generated shims: \{plan.shim_sources.length()}\n")
  builder.write_string(
    "- Review required: \{has_unresolved_breaking_changes(plan)}\n\n",
  )
  builder.write_string("## Changes\n\n")
  if plan.changes.is_empty() {
    builder.write_string("No public API changes detected.\n")
  } else {
    builder.write_string("| Status | Kind | Old | New | Reason |\n")
    builder.write_string("| --- | --- | --- | --- | --- |\n")
    for change in plan.changes {
      builder.write_string(
        "| \{change_marker(change)} | \{symbol_kind_name(change.symbol_kind)} | \{optional_name(change.old_name)} | \{optional_name(change.new_name)} | \{change.reason} |\n",
      )
    }
  }
  if !plan.diagnostics.is_empty() {
    builder.write_string("\n## Suggestions\n\n")
    for diagnostic in plan.diagnostics {
      builder.write_string("- \{diagnostic}\n")
    }
  }
  if !plan.shim_sources.is_empty() {
    builder.write_string("\n## Generated shims\n\n")
    builder.write_string("```mbt\n")
    for shim in plan.shim_sources {
      builder.write_string(shim)
    }
    builder.write_string("```\n")
  }
  builder.to_string()
}

///|
/// Merges all generated declarations into one compilable source file.
pub fn render_shim_source(plan : MigrationPlan) -> String {
  let builder = StringBuilder()
  builder.write_string(
    "// Generated by MoonShim. Review before committing.\n\n",
  )
  for shim in plan.shim_sources {
    builder.write_string(shim)
    builder.write_char('\n')
  }
  builder.to_string()
}

///|
/// Renders a stable machine-readable report suitable for CI.
pub fn render_json(
  plan : MigrationPlan,
  old_name : StringView,
  new_name : StringView,
) -> String {
  let builder = StringBuilder()
  builder.write_string("{\n")
  builder.write_string("  \"schema_version\": 1,\n")
  builder.write_string("  \"old_interface\": \"\{json_escape(old_name)}\",\n")
  builder.write_string("  \"new_interface\": \"\{json_escape(new_name)}\",\n")
  builder.write_string(
    "  \"review_required\": \{has_unresolved_breaking_changes(plan)},\n",
  )
  builder.write_string("  \"changes\": [")
  for index, change in plan.changes {
    if index > 0 {
      builder.write_char(',')
    }
    builder.write_string("\n    {")
    builder.write_string("\"status\": \"\{change_marker(change)}\", ")
    builder.write_string(
      "\"change\": \"\{change_kind_name(change.change_kind)}\", ",
    )
    builder.write_string(
      "\"kind\": \"\{symbol_kind_name(change.symbol_kind)}\", ",
    )
    builder.write_string("\"old_name\": ")
    match change.old_name {
      Some(name) => builder.write_string("\"\{json_escape(name)}\"")
      None => builder.write_string("null")
    }
    builder.write_string(", \"new_name\": ")
    match change.new_name {
      Some(name) => builder.write_string("\"\{json_escape(name)}\"")
      None => builder.write_string("null")
    }
    builder.write_string(", \"reason\": \"\{json_escape(change.reason)}\"}")
  }
  if !plan.changes.is_empty() {
    builder.write_string("\n  ")
  }
  builder.write_string("],\n")
  builder.write_string("  \"diagnostics\": [")
  for index, diagnostic in plan.diagnostics {
    if index > 0 {
      builder.write_char(',')
    }
    builder.write_string("\n    \"\{json_escape(diagnostic)}\"")
  }
  if !plan.diagnostics.is_empty() {
    builder.write_string("\n  ")
  }
  builder.write_string("],\n")
  builder.write_string("  \"shim_count\": \{plan.shim_sources.length()}\n")
  builder.write_string("}\n")
  builder.to_string()
}