///|
/// Runnable example: apply an RFC 6902 patch, compute a diff, and apply
/// an RFC 7386 merge patch. Run with:
///
/// ```bash
/// moon run examples/basic
/// ```
fn parse(text : String) -> Json {
  @json.parse(text) catch {
    _ => abort("example fixture is not valid JSON")
  }
}

///|
fn main {
  // RFC 6902: apply a patch document (test / replace / add / remove).
  let doc = parse(
    "{\"name\": \"moonbit-jsonpatch\", \"version\": 1, \"tags\": [\"json\"]}",
  )
  let patch = parse(
    "[{\"op\": \"test\", \"path\": \"/version\", \"value\": 1}, {\"op\": \"replace\", \"path\": \"/version\", \"value\": 2}, {\"op\": \"add\", \"path\": \"/tags/-\", \"value\": \"rfc6902\"}, {\"op\": \"remove\", \"path\": \"/name\"}]",
  )
  match @jsonpatch.apply_patch(doc, patch) {
    Ok(result) => println("apply: \{result.stringify()}")
    Err(e) => println("apply failed: \{e.message}")
  }

  // diff: generate a patch transforming one document into another,
  // then verify it round-trips.
  let old = parse("{\"a\": 1, \"b\": [1, 2]}")
  let new = parse("{\"a\": 2, \"b\": [1, 2, 3]}")
  let generated = @jsonpatch.diff(old, new)
  println("diff:  \{generated.stringify()}")
  match @jsonpatch.apply_patch(old, generated) {
    Ok(result) => println("roundtrip ok: \{@jsonpatch.json_equal(result, new)}")
    Err(e) => println("unexpected: \{e.message}")
  }

  // RFC 7386: merge patch — null deletes a member, objects merge
  // recursively.
  let target = parse(
    "{\"title\": \"hello\", \"author\": {\"name\": \"Xu\", \"email\": \"x@y.z\"}}",
  )
  let merge = parse("{\"title\": \"hi\", \"author\": {\"email\": null}}")
  println("merge: \{@jsonpatch.merge_patch(target, merge).stringify()}")

  // Error reporting: failures name the operation and the exact path.
  let bad = parse("[{\"op\": \"add\", \"path\": \"/a/x\", \"value\": 1}]")
  match @jsonpatch.apply_patch(parse("{\"a\": 1}"), bad) {
    Ok(_) => println("unexpected success")
    Err(e) =>
      println(
        "error: operation \{e.index} (\{e.op}) at \{e.path}: \{e.message}",
      )
  }
}