// Copyright 2026 Leo Cheng
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
/// `StreamingResponse` / `StreamHandler`: a multi-chunk body, response trailers,
/// and 103 Early Hints. `events` lowers it to the exact wire sequence a server
/// sends; `TestClient::from_stream` and `run_http_stream` drive it and the
/// client reassembles the chunks into one contiguous body.
///
///     moon run src/examples/04-streaming
#coverage.skip
fn main {
  let header = fn(r : @moonasgi.TestResponse, n : String) -> String {
    match r.header(n) {
      Some(v) => v
      None => "-"
    }
  }
  let sse : @moonasgi.StreamHandler = fn(_req) {
    @moonasgi.StreamingResponse::new(
      status=200,
      headers=[("content-type", "text/event-stream")],
      chunks=[b"data: 233\n\n", b"data: 666\n\n", b"data: done\n\n"],
      trailers=[("x-digest", "heke1228")],
      early_hints=[["; rel=preload"], ["; rel=preload"]],
    )
  }
  // events() lowers the stream to the exact outbound event sequence.
  let events = sse({
    http_method: "GET",
    path: "/events",
    query_string: b"",
    headers: [],
    body: b"",
  }).events()
  let well_formed = @moonasgi.validate_http_response(events) is None
  println("lowered to \{events.length()} events; well-formed: \{well_formed}")
  // The client reassembles the chunks into one contiguous body.
  let c = @moonasgi.TestClient::from_stream(sse)
  let r = c.get("/events")
  println("status  = \{r.status} (\{header(r, "content-type")})")
  println("body    = " + r.text())
  let digest = match r.trailer("x-digest") {
    Some(v) => v
    None => "-"
  }
  println("trailer x-digest = " + digest)
  println("early hints: \{r.early_hints.length()} messages")
  for hint in r.early_hints {
    println("  " + hint.join(", "))
  }
  // run_http_stream drives the same handler at the raw Scope/Event seam.
  let scope = @moonasgi.Scope::Http(
    @moonasgi.HttpScope::new(http_method="GET", path="/events"),
  )
  let raw = @moonasgi.run_http_stream(sse, scope, [
    @spec.HttpRequest(body=b"", more_body=false),
  ])
  println("run_http_stream -> \{raw.length()} events")
}