///|
/// Runtime response state for wasm handlers
pub(all) struct WasmResponseState {
  mut status : Int
  mut headers : Map[String, String]
  mut body : String
  mut sent : Bool
}

///|
pub fn WasmResponseState::new() -> WasmResponseState {
  { status: 200, headers: {}, body: "", sent: false }
}

///|
/// Wasm platform-specific context data
pub(all) struct PlatformContext {
  request_body : String
  state : Ref[WasmResponseState]
}

///|
pub fn PlatformContext::new(
  request_body : String,
  state : Ref[WasmResponseState],
) -> PlatformContext {
  { request_body, state }
}

///|
/// Keep Context::body async-compatible in wasm target
async fn wasm_async_checkpoint() -> Unit {
  ignore(@async.with_timeout_opt(1, async fn() { () }))
}

///|
/// Create a new Context (wasm-specific constructor)
pub fn Context::new(
  request : @http.Request,
  params : @router.Params,
  request_body : String,
  state : Ref[WasmResponseState],
) -> Context {
  let exec_ctx = ExecutionContext::new()
  let env = EmptyEnv::new()
  {
    request,
    params,
    platform: PlatformContext::new(request_body, state),
    data: Map::new(),
    vars: Variables::new(),
    exec_ctx,
    env,
    cached_body: None,
    cached_query: None,
    cached_cookies: None,
    response_headers: {},
    status: 200,
    response_sent: false,
  }
}

///|
/// Create a new Context with environment and execution context (wasm-specific)
pub fn[E : Env, C : ExecCtx] Context::with_env(
  request : @http.Request,
  params : @router.Params,
  request_body : String,
  state : Ref[WasmResponseState],
  env : E,
  exec_ctx : C,
) -> Context {
  {
    request,
    params,
    platform: PlatformContext::new(request_body, state),
    data: Map::new(),
    vars: Variables::new(),
    exec_ctx,
    env,
    cached_body: None,
    cached_query: None,
    cached_cookies: None,
    response_headers: {},
    status: 200,
    response_sent: false,
  }
}

///|
fn set_wasm_response(
  ctx : Context,
  status : Int,
  headers : Map[String, String],
  body : String,
) -> Unit {
  ctx.status = status
  ctx.platform.state.val.status = status
  ctx.platform.state.val.headers = headers
  ctx.platform.state.val.body = body
  ctx.platform.state.val.sent = true
  ctx.response_sent = true
}

///|
/// Read request body as string (wasm implementation)
pub async fn Context::body(self : Context) -> String {
  wasm_async_checkpoint()
  match self.cached_body {
    Some(body) => body
    None => {
      let body = self.platform.request_body
      self.cached_body = Some(body)
      body
    }
  }
}

///|
/// Send a text response (wasm implementation)
pub fn Context::text(self : Context, body : String, status? : Int) -> Unit {
  let status = status.unwrap_or(self.status)
  let headers = merge_headers(self.response_headers, {
    "Content-Type": "text/plain; charset=utf-8",
  })
  set_wasm_response(self, status, headers, body)
}

///|
/// Send a JSON response (wasm implementation)
pub fn Context::json(self : Context, data : Json, status? : Int) -> Unit {
  let status = status.unwrap_or(self.status)
  let headers = merge_headers(self.response_headers, {
    "Content-Type": "application/json",
  })
  set_wasm_response(self, status, headers, data.stringify())
}

///|
/// Send an HTML response (wasm implementation)
pub fn Context::html(self : Context, body : String, status? : Int) -> Unit {
  let status = status.unwrap_or(self.status)
  let headers = merge_headers(self.response_headers, {
    "Content-Type": "text/html; charset=utf-8",
  })
  set_wasm_response(self, status, headers, body)
}

///|
/// Send a redirect response (wasm implementation)
pub fn Context::redirect(self : Context, url : String) -> Unit {
  let headers = merge_headers(self.response_headers, { "Location": url })
  set_wasm_response(self, 302, headers, "")
}

///|
/// Send a 404 Not Found response (wasm implementation)
pub fn Context::not_found(self : Context) -> Unit {
  self.text("Not Found", status=404)
}

///|
/// Start an SSE response (wasm implementation)
pub fn Context::sse_start(self : Context) -> Unit {
  let headers = merge_headers(self.response_headers, {
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
  })
  self.platform.state.val.status = self.status
  self.platform.state.val.headers = headers
  self.platform.state.val.body = ""
  self.platform.state.val.sent = true
  self.response_sent = true
}

///|
/// Write raw data to the response (wasm implementation)
pub fn Context::write_raw(self : Context, data : String) -> Unit {
  if not(self.platform.state.val.sent) {
    self.platform.state.val.status = self.status
    self.platform.state.val.headers = self.response_headers
    self.platform.state.val.body = ""
    self.platform.state.val.sent = true
    self.response_sent = true
  }
  self.platform.state.val.body = self.platform.state.val.body + data
}

///|
/// End the response (wasm implementation)
pub fn Context::end_response(self : Context) -> Unit {
  if not(self.platform.state.val.sent) {
    self.platform.state.val.status = self.status
    self.platform.state.val.headers = self.response_headers
    self.platform.state.val.body = ""
  }
  self.platform.state.val.sent = true
  self.response_sent = true
}