// 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.

///|
/// HTTP/2 (and HTTP/3) pseudo-header lowering. `HttpScope::from_h2_headers`
/// consumes a HEADERS block - `:method` / `:scheme` / `:authority` / `:path`
/// pseudo-headers interleaved with ordinary fields - into a typed `HttpScope`:
/// the request line comes from the pseudo-headers, `host` is synthesised from
/// `:authority`, and no `:`-prefixed name reaches the app. A malformed set is
/// rejected with the exact `Http2HeaderError`.
///
///     moon run src/examples/10-http2
#coverage.skip
fn main {
  let describe = fn(e : @moonasgi.Http2HeaderError) -> String {
    match e {
      @spec.MissingMethod => "missing :method"
      @spec.MissingScheme => "missing :scheme"
      @spec.MissingPath => "missing :path"
      @spec.EmptyPath => "empty :path"
      @spec.DuplicatePseudoHeader(n) => "duplicate " + n
      @spec.UnknownPseudoHeader(n) => "unknown " + n
      @spec.PseudoHeaderAfterRegular(n) => "pseudo after regular: " + n
    }
  }
  // A well-formed h2 HEADERS block lowers onto a scope.
  let frame = [
    (":method", "POST"),
    (":scheme", "https"),
    (":authority", "example.test"),
    (":path", "/items?page=2&q=heke1228"),
    ("content-type", "application/json"),
    ("accept", "*/*"),
  ]
  match @moonasgi.HttpScope::from_h2_headers(frame) {
    Ok(s) => {
      println(
        "method=\{s.http_method} scheme=\{s.scheme} version=\{s.http_version}",
      )
      println("path=\{s.path} query=\{@moonasgi.latin1_decode(s.query_string)}")
      let hdrs = s.headers.map(fn(kv) { kv.0 + ": " + kv.1 })
      println("headers: " + hdrs.join(" | "))
    }
    Err(e) => println("unexpected: " + describe(e))
  }
  // The same contract serves HTTP/3 - pass http_version="3".
  match
    @moonasgi.HttpScope::from_h2_headers(
      [(":method", "GET"), (":scheme", "https"), (":path", "/"), ("host", "h")],
      http_version="3",
    ) {
    Ok(s) => println("h3 version=\{s.http_version}")
    Err(e) => println("unexpected: " + describe(e))
  }
  // Each malformed pseudo-header set is rejected with its exact violation.
  let bad : Array[(String, Array[(String, String)])] = [
    ("missing :method", [(":scheme", "https"), (":path", "/")]),
    (
      "unknown :foo",
      [(":method", "GET"), (":scheme", "h"), (":path", "/"), (":foo", "x")],
    ),
    (
      "pseudo after regular",
      [(":method", "GET"), ("a", "b"), (":scheme", "h"), (":path", "/")],
    ),
  ]
  for case in bad {
    match @moonasgi.HttpScope::from_h2_headers(case.1) {
      Ok(_) => println(case.0 + " -> unexpectedly Ok")
      Err(e) => println(case.0 + " -> " + describe(e))
    }
  }
}