///|
/// Type-safe render: TuiAttrValue -> crater Style
/// No string parsing needed - direct pattern matching
///
/// This will be the main render path when luna supports Attr[E, A]

///|
/// Apply typed attribute to crater style
fn apply_typed_attr(style : @style.Style, attr : TuiAttrValue) -> Unit {
  match attr {
    TuiAttrValue::Direction(v) => style.flex_direction = v.to_flex_direction()
    TuiAttrValue::Width(v) => style.width = v.to_dimension()
    TuiAttrValue::Height(v) => style.height = v.to_dimension()
    TuiAttrValue::MinWidth(v) => style.min_width = v.to_dimension()
    TuiAttrValue::MinHeight(v) => style.min_height = v.to_dimension()
    TuiAttrValue::FlexGrow(v) => style.flex_grow = v
    TuiAttrValue::FlexShrink(v) => style.flex_shrink = v
    TuiAttrValue::Gap(v) => {
      style.row_gap = @values.Dimension::Length(v)
      style.column_gap = @values.Dimension::Length(v)
    }
    // Display
    TuiAttrValue::Display(v) => style.display = v.to_display()
    // Grid container
    TuiAttrValue::GridTemplateColumns(v) => style.grid_template_columns = v
    TuiAttrValue::GridTemplateRows(v) => style.grid_template_rows = v
    TuiAttrValue::GridAutoFlow(v) =>
      style.grid_auto_flow = v.to_grid_auto_flow()
    // Grid item
    TuiAttrValue::GridColumn(v) =>
      style.grid_column = {
        start: @values.GridPlacement::Line(v),
        end: @values.GridPlacement::Auto,
      }
    TuiAttrValue::GridRow(v) =>
      style.grid_row = {
        start: @values.GridPlacement::Line(v),
        end: @values.GridPlacement::Auto,
      }
    TuiAttrValue::GridColumnSpan(v) =>
      style.grid_column = {
        start: style.grid_column.start,
        end: @values.GridPlacement::Span(v),
      }
    TuiAttrValue::GridRowSpan(v) =>
      style.grid_row = {
        start: style.grid_row.start,
        end: @values.GridPlacement::Span(v),
      }
    TuiAttrValue::Padding(v) => {
      let len = @values.Dimension::Length(v)
      style.padding = @values.Rect::new(len, len, len, len)
    }
    TuiAttrValue::PaddingX(v) => {
      let len = @values.Dimension::Length(v)
      let current = style.padding
      style.padding = @values.Rect::new(current.top, len, current.bottom, len)
    }
    TuiAttrValue::PaddingY(v) => {
      let len = @values.Dimension::Length(v)
      let current = style.padding
      style.padding = @values.Rect::new(len, current.right, len, current.left)
    }
    TuiAttrValue::Margin(v) => {
      let len = @values.Dimension::Length(v)
      style.margin = @values.Rect::new(len, len, len, len)
    }
    TuiAttrValue::MarginX(v) => {
      let len = @values.Dimension::Length(v)
      let current = style.margin
      style.margin = @values.Rect::new(current.top, len, current.bottom, len)
    }
    TuiAttrValue::MarginY(v) => {
      let len = @values.Dimension::Length(v)
      let current = style.margin
      style.margin = @values.Rect::new(len, current.right, len, current.left)
    }
    TuiAttrValue::Justify(v) => style.justify_content = v.to_alignment()
    TuiAttrValue::Align(v) => style.align_items = v.to_alignment()
    TuiAttrValue::Border(v) =>
      match v.to_border_chars() {
        Some(_) => {
          let one = @values.Dimension::Length(1.0)
          style.border = @values.Rect::new(one, one, one, one)
        }
        None => ()
      }
    // Visual attributes are handled separately in RenderStyle
    TuiAttrValue::BorderColor(_) => ()
    TuiAttrValue::Fg(_) => ()
    TuiAttrValue::Bg(_) => ()
    TuiAttrValue::Bold(_) => ()
    TuiAttrValue::Underline(_) => ()
    TuiAttrValue::Id(_) => ()
    // Accessibility attributes are handled separately
    TuiAttrValue::TabIndex(_) => ()
    TuiAttrValue::Role(_) => ()
    // Grid template areas: handled in convert_element for context passing
    TuiAttrValue::GridTemplateAreas(_) => ()
    // Grid area: resolved in convert_element_with_area
    TuiAttrValue::GridArea(_) => ()
  }
}

///|
/// Extract visual style from typed attributes
fn extract_render_style(
  attrs : Array[TuiAttrValue],
) -> (
  @core.Color?, // fg
  @core.Color?, // bg
  Bool, // bold
  Bool, // underline
  @core.BorderChars?, // border
  @core.Color?,
) { // border_color
  let mut fg : @core.Color? = None
  let mut bg : @core.Color? = None
  let mut bold = false
  let mut underline = false
  let mut border : @core.BorderChars? = None
  let mut border_color : @core.Color? = None
  for attr in attrs {
    match attr {
      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
      TuiAttrValue::Border(v) => border = v.to_border_chars()
      TuiAttrValue::BorderColor(v) => border_color = Some(v.to_color())
      _ => ()
    }
  }
  (fg, bg, bold, underline, border, border_color)
}

// extract_id is not used yet - will be needed when luna supports Attr[E, A]
// fn extract_id(attrs : Array[TuiAttrValue]) -> String? {
//   for attr in attrs {
//     match attr {
//       TuiAttrValue::Id(id) => return Some(id)
//       _ => continue
//     }
//   }
//   None
// }

///|
/// Context for typed rendering
pub struct TypedRenderContext {
  styles : Map[String, @core.RenderStyle]
  texts : Map[String, String]
  handlers : Map[String, (TuiEvent) -> Unit]
  roles : Map[String, @core.Role]
  mut id_counter : Int
  // Stack of grid area maps (for nested grids) - mirrors RenderContext
  area_stack : Array[Map[String, GridAreaInfo]]
}

///|
pub fn TypedRenderContext::new() -> TypedRenderContext {
  {
    styles: {},
    texts: {},
    handlers: {},
    roles: {},
    id_counter: 0,
    area_stack: [],
  }
}

///|
fn TypedRenderContext::gen_id(self : TypedRenderContext) -> String {
  self.id_counter = self.id_counter + 1
  "t" + self.id_counter.to_string()
}

///|
/// Convert BoxProps directly to crater node (type-safe path)
pub fn box_to_crater(
  ctx : TypedRenderContext,
  props : BoxProps,
  children : Array[TuiNode],
) -> @node.Node {
  let id = if props.id.length() > 0 { props.id } else { ctx.gen_id() }
  let attrs = props.to_attrs()
  for attr in attrs {
    match attr {
      TuiAttrValue::Role(role) => ctx.roles[id] = role
      _ => ()
    }
  }
  // Apply layout attributes to style
  let style = @style.Style::default()
  style.display = @values.Display::Flex
  for attr in attrs {
    apply_typed_attr(style, attr)
  }
  // Extract visual style
  let (fg, bg, bold, underline, border, border_color) = extract_render_style(
    attrs,
  )
  if fg is Some(_) || bg is Some(_) || bold || underline || border is Some(_) {
    ctx.styles[id] = {
      fg: fg.unwrap_or(@core.Color::white()),
      bg: bg.unwrap_or(@core.Color::transparent()),
      bold,
      underline,
      border,
      border_fg: border_color.unwrap_or(@core.Color::white()),
    }
  }
  // Convert children recursively
  let crater_children = children.map(fn(c) { typed_to_crater_node(ctx, c) })
  @node.Node::new(id, style, crater_children)
}

///|
/// Convert TuiNode to crater node using typed render context
/// This version still parses strings but uses TypedRenderContext
/// Will be replaced when luna supports Attr[E, A]
fn typed_to_crater_node(ctx : TypedRenderContext, node : TuiNode) -> @node.Node {
  // Delegate to string-based render for now
  // This will be replaced with typed rendering when luna is updated
  let string_ctx : RenderContext = {
    styles: ctx.styles,
    texts: ctx.texts,
    handlers: ctx.handlers,
    roles: ctx.roles,
    id_counter: ctx.id_counter,
    area_stack: ctx.area_stack,
  }
  let result = to_crater_node(string_ctx, node)
  ctx.id_counter = string_ctx.id_counter
  result
}