///|
/// A multi-file spec, a naming style, and the layered project tree — the three
/// things that separate `mctl gen api` from a single generated file. The entry spec
/// imports `user.api`, so its type and its grouped route are merged in; the tree is
/// then named in `go_zero` and written out; and the second pass shows what a
/// regeneration would actually touch once the first one is on disk.
///
///     moon run src/examples/13-tree
#coverage.skip
fn main raise {
  let files : Map[String, String] = Map([
    (
      "spec/user.api",
      (
        #|type LoginReq {
        #|  name: string `json:"name"`
        #|}
        #|
        #|@server(group: user, prefix: /api/v1, middleware: Log)
        #|service greet {
        #|  @doc "log a user in"
        #|  @handler login
        #|  post /login (LoginReq)
        #|}
      ),
    ),
  ])
  let source =
    #|import "user.api"
    #|
    #|service greet {
    #|  @handler get_one
    #|  get /one
    #|}
  println("==== imports ====\n")
  for dep in @moonctl.deps(source, from="spec/greet.api") {
    println("  spec/greet.api -> \{dep}")
  }
  let spec = @moonctl.parse_all(source, files, from="spec/greet.api")
  println(
    "\nmerged: \{spec.types.length()} type(s), \{spec.routes.length()} route(s)",
  )
  for r in spec.routes {
    println("  \{r.verb} \{r.path} -> \{r.handler}")
  }
  println("\n==== style ====\n")
  for template in ["gozero", "goZero", "go_zero", "Go#zero"] {
    println(
      "  \{template} -> \{@moonctl.Style::parse(template).format("welcome_to_go_zero")}",
    )
  }
  println("\n==== tree (--style go_zero) ====\n")
  let tree = @moonctl.generate_tree(
    spec,
    style=@moonctl.Style::parse("go_zero"),
  )
  for f in tree {
    println("  \{f.path}")
  }
  println("\n==== the second run ====\n")
  let written : Map[String, Bool] = Map([])
  for f in @moonctl.tree_plan(tree, _ => false) {
    written[f.path] = true
  }
  println(
    "first run wrote \{written.length()} file(s); running again would write:",
  )
  for f in @moonctl.tree_plan(tree, p => written.contains(p)) {
    println("  \{f.path}")
  }
  println(
    "\neverything else is yours once it exists — handler and logic bodies included.",
  )
}