///|
/// Query Selector Implementation
///
/// Simple CSS selector support for querying DOM nodes.
/// Supports: tag names, #id, .class, [attr], [attr=value]

///|
/// Query selector (simple CSS selector support)
/// Returns first matching node
pub fn DomTree::query_selector(
  self : DomTree,
  root : NodeId,
  selector : String,
) -> Result[NodeId?, CoreError] {
  match self.query_selector_all(root, selector) {
    Ok(results) =>
      if results.length() > 0 {
        Ok(Some(results[0]))
      } else {
        Ok(None)
      }
    Err(e) => Err(e)
  }
}

///|
/// Query selector all
/// Returns all matching nodes
pub fn DomTree::query_selector_all(
  self : DomTree,
  root : NodeId,
  selector : String,
) -> Result[Array[NodeId], CoreError] {
  let root_id = root.to_int()
  match self.nodes.get(root_id) {
    None => Err(NodeNotFound(node_id=root))
    Some(_) => {
      let results : Array[NodeId] = []
      self.query_recursive(root_id, selector, results)
      Ok(results)
    }
  }
}

///|
/// Recursive query helper
fn DomTree::query_recursive(
  self : DomTree,
  node_id : Int,
  selector : String,
  results : Array[NodeId],
) -> Unit {
  let node = self.nodes.get(node_id)
  guard node is Some(node) else { return }
  // Check if this node matches
  if self.matches_selector(node, selector) {
    results.push(NodeId(node_id))
  }
  // Recurse into children
  for child_id in node.children {
    self.query_recursive(child_id, selector, results)
  }
}

///|
/// Check if node matches selector (simplified)
fn DomTree::matches_selector(
  self : DomTree,
  node : DomNode,
  selector : String,
) -> Bool {
  // Suppress unused warning
  let _ = self
  // Only match elements
  guard node.node_type == Element else { return false }
  // Simple selector matching
  if selector.has_prefix("#") {
    // ID selector
    let id = selector[1:].to_string() catch { _ => return false }
    node.attributes.get("id") == Some(id)
  } else if selector.has_prefix(".") {
    // Class selector
    let class_name = selector[1:].to_string() catch { _ => return false }
    match node.attributes.get("class") {
      Some(classes) => classes.contains(class_name)
      None => false
    }
  } else if selector.has_prefix("[") && selector.has_suffix("]") {
    // Attribute selector (simple: [attr] or [attr=value])
    let inner = selector[1:selector.length() - 1].to_string() catch {
      _ => return false
    }
    if inner.contains("=") {
      match split_once(inner, '=') {
        Some((attr, value)) => {
          let clean_value = value.trim().to_string()
          let clean_value = if clean_value.has_prefix("\"") &&
            clean_value.has_suffix("\"") {
            clean_value[1:clean_value.length() - 1].to_string() catch {
              _ => clean_value
            }
          } else {
            clean_value
          }
          node.attributes.get(attr.trim().to_string()) == Some(clean_value)
        }
        None => false
      }
    } else {
      node.attributes.contains(inner)
    }
  } else {
    // Tag name selector
    node.tag_name.to_lower() == selector.to_lower()
  }
}

///|
/// Split string on first occurrence of character
fn split_once(s : String, c : Char) -> (String, String)? {
  let chars = s.to_array()
  for i, ch in chars {
    if ch == c {
      let before = StringBuilder::new()
      let after = StringBuilder::new()
      for j = 0; j < i; j = j + 1 {
        before.write_char(chars[j])
      }
      for j = i + 1; j < chars.length(); j = j + 1 {
        after.write_char(chars[j])
      }
      return Some((before.to_string(), after.to_string()))
    }
  }
  None
}