///|
/// Inline rendering for TuiNodes
/// Renders nodes to an array of lines with ANSI colors
/// No screen clearing or cursor positioning - suitable for inline CLI prompts

///|
/// Inline visual context for tracking text styles
priv struct InlineStyle {
  fg : @core.Color?
  bg : @core.Color?
  bold : Bool
  underline : Bool
}

///|
fn InlineStyle::default() -> InlineStyle {
  { fg: None, bg: None, bold: false, underline: false }
}

///|
/// Merge two optional colors (child overrides parent)
fn merge_color(child : @core.Color?, parent : @core.Color?) -> @core.Color? {
  match child {
    Some(_) => child
    None => parent
  }
}

///|
/// Apply inline style to text, returning ANSI-escaped string
fn apply_inline_style(text : String, style : InlineStyle) -> String {
  let mut prefix = ""
  if style.bold {
    prefix = prefix + @render.ansi_bold()
  }
  if style.underline {
    prefix = prefix + @render.ansi_underline()
  }
  match style.fg {
    Some(color) => prefix = prefix + @render.ansi_fg_color(color)
    None => ()
  }
  match style.bg {
    Some(color) => prefix = prefix + @render.ansi_bg_color(color)
    None => ()
  }
  if prefix.length() > 0 {
    prefix + text + @render.ansi_reset()
  } else {
    text
  }
}

///|
/// Extract inline style from element attributes
fn extract_inline_style(
  el : @luna.VElement[TuiEvent, TuiAttrValue],
) -> InlineStyle {
  let mut fg : @core.Color? = None
  let mut bg : @core.Color? = None
  let mut bold = false
  let mut underline = false
  for attr in el.attrs {
    let (_, value) = attr
    match value {
      @luna.Attr::VStatic(typed_value) =>
        match typed_value {
          TuiAttrValue::Fg(v) => fg = Some(v.to_color())
          TuiAttrValue::Bg(v) => bg = Some(v.to_color())
          TuiAttrValue::Bold(v) => bold = v
          TuiAttrValue::Underline(v) => underline = v
          _ => ()
        }
      @luna.Attr::VDynamic(getter) =>
        match getter() {
          TuiAttrValue::Fg(v) => fg = Some(v.to_color())
          TuiAttrValue::Bg(v) => bg = Some(v.to_color())
          TuiAttrValue::Bold(v) => bold = v
          TuiAttrValue::Underline(v) => underline = v
          _ => ()
        }
      _ => ()
    }
  }
  { fg, bg, bold, underline }
}

///|
/// Check if element is a row (horizontal layout)
fn is_row(el : @luna.VElement[TuiEvent, TuiAttrValue]) -> Bool {
  for attr in el.attrs {
    let (_, value) = attr
    match value {
      @luna.Attr::VStatic(TuiAttrValue::Direction(Row)) => return true
      @luna.Attr::VStatic(TuiAttrValue::Direction(Column)) => return false
      @luna.Attr::VDynamic(getter) =>
        match getter() {
          TuiAttrValue::Direction(Row) => return true
          TuiAttrValue::Direction(Column) => return false
          _ => ()
        }
      _ => ()
    }
  }
  // Default: row tag is row, everything else is column
  el.tag == "row"
}

///|
/// Render a TuiNode to a single string (for horizontal concatenation)
fn render_inline_text(node : TuiNode, parent_style : InlineStyle) -> String {
  match node {
    @luna.Node::Text(content) => apply_inline_style(content, parent_style)
    @luna.Node::DynamicText(getter) =>
      apply_inline_style(getter(), parent_style)
    @luna.Node::Element(el) => {
      let style = extract_inline_style(el)
      // Merge with parent style (child overrides)
      let merged : InlineStyle = {
        fg: merge_color(style.fg, parent_style.fg),
        bg: merge_color(style.bg, parent_style.bg),
        bold: style.bold || parent_style.bold,
        underline: style.underline || parent_style.underline,
      }
      match el.tag {
        "text" => {
          // Text element - extract text content from children
          let mut text_content = ""
          for child in el.children {
            match child {
              @luna.Node::Text(content) => text_content = content
              @luna.Node::DynamicText(getter) => text_content = getter()
              _ => ()
            }
          }
          apply_inline_style(text_content, merged)
        }
        "spacer" => " "
        "hspace" => " "
        _ => {
          // Container - concatenate children
          let parts : Array[String] = []
          for child in el.children {
            parts.push(render_inline_text(child, merged))
          }
          parts.join("")
        }
      }
    }
    @luna.Node::Fragment(children) => {
      let parts : Array[String] = []
      for child in children {
        parts.push(render_inline_text(child, parent_style))
      }
      parts.join("")
    }
    @luna.Node::Show(condition~, child~) =>
      if condition() {
        render_inline_text(child(), parent_style)
      } else {
        ""
      }
    @luna.Node::For(render~) => {
      let items = render()
      let parts : Array[String] = []
      for item in items {
        parts.push(render_inline_text(item, parent_style))
      }
      parts.join("")
    }
    @luna.Node::Component(render~) => render_inline_text(render(), parent_style)
    _ => ""
  }
}

///|
/// Render a TuiNode to an array of lines
/// Each line is a complete string with ANSI escape codes
pub fn render_to_lines(node : TuiNode) -> Array[String] {
  render_to_lines_with_style(node, InlineStyle::default())
}

///|
/// Render a TuiNode as an overlay at specified position
/// Returns ANSI string with cursor positioning commands
/// Each line of the node is rendered at (x + i, y) for i-th line
pub fn render_overlay_at(x : Int, y : Int, node : TuiNode) -> String {
  let lines = render_to_lines(node)
  let buf = StringBuilder::new()
  for i, line in lines {
    // Move cursor to position (row, col) - ANSI uses 1-indexed coordinates
    buf.write_string(@render.ansi_move_to(y + i, x))
    buf.write_string(line)
  }
  buf.to_string()
}

///|
/// Render with inherited style
fn render_to_lines_with_style(
  node : TuiNode,
  parent_style : InlineStyle,
) -> Array[String] {
  match node {
    @luna.Node::Text(content) => [apply_inline_style(content, parent_style)]
    @luna.Node::DynamicText(getter) =>
      [apply_inline_style(getter(), parent_style)]
    @luna.Node::Element(el) => {
      let style = extract_inline_style(el)
      let merged : InlineStyle = {
        fg: merge_color(style.fg, parent_style.fg),
        bg: merge_color(style.bg, parent_style.bg),
        bold: style.bold || parent_style.bold,
        underline: style.underline || parent_style.underline,
      }
      match el.tag {
        "text" => {
          let mut text_content = ""
          for child in el.children {
            match child {
              @luna.Node::Text(content) => text_content = content
              @luna.Node::DynamicText(getter) => text_content = getter()
              _ => ()
            }
          }
          [apply_inline_style(text_content, merged)]
        }
        "spacer" => [""]
        "hspace" => [""]
        "vspace" => [""]
        _ =>
          if is_row(el) {
            // Row: concatenate children horizontally into one line
            let parts : Array[String] = []
            for child in el.children {
              parts.push(render_inline_text(child, merged))
            }
            [parts.join("")]
          } else {
            // Column: each child becomes one or more lines
            let lines : Array[String] = []
            for child in el.children {
              let child_lines = render_to_lines_with_style(child, merged)
              for line in child_lines {
                lines.push(line)
              }
            }
            lines
          }
      }
    }
    @luna.Node::Fragment(children) => {
      let lines : Array[String] = []
      for child in children {
        let child_lines = render_to_lines_with_style(child, parent_style)
        for line in child_lines {
          lines.push(line)
        }
      }
      lines
    }
    @luna.Node::Show(condition~, child~) =>
      if condition() {
        render_to_lines_with_style(child(), parent_style)
      } else {
        []
      }
    @luna.Node::For(render~) => {
      let items = render()
      let lines : Array[String] = []
      for item in items {
        let item_lines = render_to_lines_with_style(item, parent_style)
        for line in item_lines {
          lines.push(line)
        }
      }
      lines
    }
    @luna.Node::Component(render~) =>
      render_to_lines_with_style(render(), parent_style)
    _ => []
  }
}