// Sol - SSR-first Web Framework for MoonBit
//
// Built on top of Mars, providing SSR with Luna VNodes.
// Inspired by Next.js, Solid Start, and Qwik City.
//

///|
/// Mars app type alias
type App = @mars.Server

///|
/// Mars context type alias
type Ctx = @mars.Context

///|
/// Render a VNode to HTML string with full document wrapper
/// Use hydration=true to enable hydration markers (for pages with Islands)
pub fn[E] render_page(
  node : @luna.Node[E, String],
  title? : String,
  head? : String,
  hydration? : Bool,
) -> String {
  let title_str = title.unwrap_or("App")
  let head_str = head.unwrap_or("")
  let enable_hydration = hydration.unwrap_or(false)
  let body_html = if enable_hydration {
    @render.render_to_string_with_hydration(node)
  } else {
    @render.render_to_string(node).html
  }
  @page_shell.render_document(title_str, head_str, body_html)
}

///|
/// Render a VNode to HTML string without document wrapper (for partial/fragment responses)
pub fn[E] render_fragment(node : @luna.Node[E, String]) -> String {
  @render.render_to_string_with_hydration(node)
}

///|
/// Register a page route that renders a VNode
/// Use hydration=true for pages with Islands (adds loader script and hydration markers)
pub fn[E] page(
  app : App,
  path : String,
  render_fn : (Ctx) -> @luna.Node[E, String],
  title? : String,
  head? : String,
  hydration? : Bool,
  loader_url? : String,
) -> Unit {
  app.get(
    path,
    @mars.handler(async fn(c) {
      let node = render_fn(c)
      let enable_hydration = hydration.unwrap_or(false)
      let base_head = head.unwrap_or("")
      if enable_hydration {
        // Hydration enabled: render with hydration markers and include loader script
        let loader = loader_url.unwrap_or(default_loader_url)
        let loader_script = ""
        let full_head = @hot_reload.with_dev_head_script(
          base_head + loader_script,
        )
        let html = render_page(node, title?, head=full_head, hydration=true)
        c.html(html)
      } else {
        // Static page: render without hydration (but still add HMR in dev)
        let full_head = @hot_reload.with_dev_head_script(base_head)
        let html = render_page(node, title?, head=full_head)
        c.html(html)
      }
    }),
  )
}