// Field extractor — parse structured data from log messages

// Extract key=value pairs from a message string

///|
pub fn extract_key_value_pairs(message : String) -> Array[(String, String)] {
  extract_pairs(message, 0, 0, "", "", [])
}

///|
fn extract_pairs(
  s : String,
  idx : Int,
  state : Int,
  current_key : String,
  current_val : String,
  result : Array[(String, String)],
) -> Array[(String, String)] {
  // state: 0=reading key, 1=reading value, 2=looking for start
  if idx >= s.length() {
    if current_key != "" && current_val != "" {
      result.push((current_key, current_val))
    }
    result
  } else {
    let ch = s[idx:idx + 1].to_owned()
    if ch == "=" && state == 0 {
      extract_pairs(s, idx + 1, 1, current_key, "", result)
    } else if ch == " " && state == 1 {
      if current_key != "" && current_val != "" {
        result.push((current_key, current_val))
      }
      extract_pairs(s, idx + 1, 0, "", "", result)
    } else if state == 0 {
      extract_pairs(s, idx + 1, 0, current_key + ch, current_val, result)
    } else {
      extract_pairs(s, idx + 1, 1, current_key, current_val + ch, result)
    }
  }
}

// Extract JSON-style fields from message: {"key": "value", ...}

///|
pub fn extract_json_like(message : String) -> Array[(String, String)] {
  // Simple: look for "key":"value" patterns
  extract_json_pairs(message, 0, 0, "", "", [])
}

///|
fn extract_json_pairs(
  s : String,
  idx : Int,
  state : Int,
  current_key : String,
  current_val : String,
  result : Array[(String, String)],
) -> Array[(String, String)] {
  // state: 0=before key, 1=in key, 2=after key (looking for colon), 3=in value
  if idx >= s.length() {
    if current_key != "" {
      result.push((current_key, current_val))
    }
    result
  } else {
    let ch = s[idx:idx + 1].to_owned()
    if ch == "\"" && state == 0 {
      extract_json_pairs(s, idx + 1, 1, "", "", result)
    } else if ch == "\"" && state == 1 {
      extract_json_pairs(s, idx + 1, 2, current_key, "", result)
    } else if ch == ":" && state == 2 {
      extract_json_pairs(s, idx + 1, 3, current_key, "", result)
    } else if ch == "\"" && state == 3 {
      extract_json_pairs(s, idx + 1, 0, "", current_val, result)
    } else if state == 1 {
      extract_json_pairs(s, idx + 1, 1, current_key + ch, current_val, result)
    } else if state == 3 && ch != "\"" {
      extract_json_pairs(s, idx + 1, 3, current_key, current_val + ch, result)
    } else {
      extract_json_pairs(s, idx + 1, state, current_key, current_val, result)
    }
  }
}

// Count words in a message

///|
pub fn word_count(message : String) -> Int {
  count_words(message, 0, 0, false)
}

///|
fn count_words(s : String, idx : Int, count : Int, in_word : Bool) -> Int {
  if idx >= s.length() {
    if in_word {
      count + 1
    } else {
      count
    }
  } else {
    let ch = s[idx:idx + 1].to_owned()
    if ch == " " || ch == "\t" || ch == "\n" {
      count_words(s, idx + 1, if in_word { count + 1 } else { count }, false)
    } else {
      count_words(s, idx + 1, count, true)
    }
  }
}