// examples/serialization_studio — runnable demonstration of the
// `src/serialization` direction as a realistic schema workflow: parse and
// validate a .proto covering scalars / repeated / nested / enum / oneof /
// map, round-trip a typed message through wire bytes and JSON, produce
// canonical bytes, detect breaking schema changes, and generate MoonBit
// bindings.
//
// Run with:
//   moon run examples/serialization_studio

///|
fn main {
  println("=== 1. parse + validate .proto (UserProfile) ===")
  let schema = match @ser.parse_proto_full(@ser.demo_proto()) {
    Ok(s) => s
    Err(e) => {
      println("parse error: \{e}")
      return
    }
  }
  match @ser.validate_schema(schema) {
    Ok(_) =>
      println(
        "valid schema: \{schema.messages.length()} messages, \{schema.enums.length()} enums",
      )
    Err(errors) => {
      for e in errors {
        println("schema error: \{e}")
      }
      return
    }
  }
  println("")
  println("=== 2. typed encode/decode round-trip ===")
  let msg = @ser.demo_message()
  let bytes = match @ser.encode_typed(schema, @ser.demo_message_name, msg) {
    Ok(b) => b
    Err(e) => {
      println("encode error: \{e}")
      return
    }
  }
  println("wire size : \{bytes.length()} bytes")
  match @ser.decode_typed(schema, @ser.demo_message_name, bytes) {
    Ok(back) => println("round-trip: decoded == original -> \{back == msg}")
    Err(e) => println("decode error: \{e}")
  }
  println("")
  println("=== 3. canonical bytes + JSON bridge ===")
  match @ser.encode_canonical(schema, @ser.demo_message_name, msg) {
    Ok(canon) =>
      println("canonical : \{canon.length()} bytes (deterministic field order)")
    Err(e) => println("canonical error: \{e}")
  }
  let json = match @ser.encode_json(schema, @ser.demo_message_name, msg) {
    Ok(j) => j
    Err(e) => {
      println("json error: \{e}")
      return
    }
  }
  println("json      : \{json}")
  match @ser.decode_json(schema, @ser.demo_message_name, json) {
    Ok(back) => println("json round-trip ok -> \{back == msg}")
    Err(e) => println("json parse error: \{e}")
  }
  println("")
  println("=== 4. corrupt wire bytes are rejected with an offset ===")
  let corrupt = b"\xff\xff\xff\xff\xff\xff"
  match @ser.decode_typed(schema, @ser.demo_message_name, corrupt) {
    Ok(_) => println("unexpectedly decoded")
    Err(e) => println("rejected  : \{e}")
  }
  println("")
  println("=== 5. schema evolution: breaking-change detection ===")
  let evolved_src = @ser.demo_proto().replace(
    old="int32 id = 1;",
    new="string id = 1;",
  )
  match @ser.parse_proto_full(evolved_src) {
    Ok(evolved) => {
      let breaks = @ser.check_schema_evolution(schema, evolved)
      for b in breaks {
        println("BREAKING field #\{b.field_number}: \{b.reason}")
      }
    }
    Err(e) => println("parse error: \{e}")
  }
  println("")
  println("=== 6. code generation (first lines) ===")
  let code = @ser.gen_moonbit_full(schema)
  let all_lines = code.split("\n").collect()
  let total = all_lines.length()
  for i in 0..<8 {
    if i < total {
      println(all_lines[i].to_owned())
    }
  }
  println("... (\{total} lines total)")
}