///|
/// Parsed SKILL.md frontmatter (flat fields only for MVP).
pub struct SkillFrontmatter {
  name : Option[String]
  description : Option[String]
  platforms : Array[String]
  /// Raw conditions extracted from metadata.hermes block
  fallback_for_tools : Array[String]
  fallback_for_toolsets : Array[String]
  requires_tools : Array[String]
  requires_toolsets : Array[String]
  /// Free-form tags from metadata.hermes.tags for downstream grouping/search.
  tags : Array[String]
}

///| Strip leading/trailing single or double quotes from a string.
fn strip_quotes(s : String) -> String {
  let s1 = if s.has_prefix("\"") && s.has_suffix("\"") && s.length() >= 2 {
    s[1:s.length() - 1].to_string()
  } else {
    s
  }
  if s1.has_prefix("'") && s1.has_suffix("'") && s1.length() >= 2 {
    s1[1:s1.length() - 1].to_string()
  } else {
    s1
  }
}

///| Extract the YAML block between --- delimiters.
/// Returns (yaml_block, body_after_delimiters) or ("", original) if no frontmatter.
fn extract_frontmatter_block(content : String) -> (String, String) {
  if !content.has_prefix("---") {
    return ("", content)
  }
  // Remove the opening --- and look for closing \n---
  let rest = content[3:].to_string() // skip opening ---
  // Use regexp to find the closing \n---\n pattern
  let re = try {
    @regexp.compile("\n---[ \t]*\n")
  } catch {
    _ => return ("", content)
  }
  match re.match_(rest) {
    None => ("", content)
    Some(mr) => {
      // before() gives us the yaml block (text before \n---\n)
      // after() gives us the body (text after \n---\n)
      let yaml_block = mr.before().to_string()
      let body = mr.after().to_string()
      (yaml_block, body)
    }
  }
}

///| Parse a YAML-flow-style list: "[a, b, c]" -> ["a", "b", "c"]
fn parse_yaml_list(value : String) -> Array[String] {
  let s = value.trim()
  if s.has_prefix("[") && s.has_suffix("]") && s.length() >= 2 {
    let inner = s[1:s.length() - 1].to_string()
    let result : Array[String] = []
    for item in inner.split(",") {
      let trimmed = strip_quotes(item.to_string().trim().to_string())
      if trimmed.length() > 0 {
        result.push(trimmed)
      }
    }
    result
  } else if s.length() > 0 {
    [s.to_string()]
  } else {
    []
  }
}

///| Extract a named list from a YAML block (single-line flow-style lists).
fn extract_list_field(yaml_block : String, key : String) -> Array[String] {
  for line in yaml_block.split("\n") {
    let trimmed = line.to_string().trim()
    if trimmed.has_prefix(key + ":") {
      let value = trimmed[key.length() + 1:].to_string().trim().to_string()
      return parse_yaml_list(value)
    }
  }
  []
}

///| Parse SKILL.md frontmatter from the full file content.
pub fn parse_frontmatter(content : String) -> SkillFrontmatter {
  let (yaml_block, _body) = extract_frontmatter_block(content)
  if yaml_block.length() == 0 {
    return {
      name: None,
      description: None,
      platforms: [],
      fallback_for_tools: [],
      fallback_for_toolsets: [],
      requires_tools: [],
      requires_toolsets: [],
      tags: [],
    }
  }

  // Parse flat key: value lines
  let mut name : Option[String] = None
  let mut description : Option[String] = None

  for line in yaml_block.split("\n") {
    let trimmed = line.to_string().trim()
    if trimmed.has_prefix("name:") {
      let v = trimmed[5:].to_string().trim().to_string()
      if v.length() > 0 {
        name = Some(v)
      }
    } else if trimmed.has_prefix("description:") {
      let v = trimmed[12:].to_string().trim().to_string()
      if v.length() > 0 {
        description = Some(v)
      }
    }
  }

  let platforms = extract_list_field(yaml_block, "platforms")
  let fallback_for_tools = extract_list_field(yaml_block, "fallback_for_tools")
  let fallback_for_toolsets = extract_list_field(
    yaml_block, "fallback_for_toolsets",
  )
  let requires_tools = extract_list_field(yaml_block, "requires_tools")
  let requires_toolsets = extract_list_field(yaml_block, "requires_toolsets")
  let tags = extract_list_field(yaml_block, "tags")

  {
    name,
    description,
    platforms,
    fallback_for_tools,
    fallback_for_toolsets,
    requires_tools,
    requires_toolsets,
    tags,
  }
}

test "parse name from frontmatter" {
  let content = "---\nname: tdd-workflow\ndescription: TDD step by step\n---\n\n# Body\n"
  let fm = parse_frontmatter(content)
  assert_eq(fm.name, Some("tdd-workflow"))
  assert_eq(fm.description, Some("TDD step by step"))
}

test "parse platforms list" {
  let content = "---\nname: foo\nplatforms: [macos, linux]\n---\nbody\n"
  let fm = parse_frontmatter(content)
  assert_eq(fm.platforms, ["macos", "linux"])
}

test "empty frontmatter for no --- delimiters" {
  let fm = parse_frontmatter("# Just a heading\n")
  assert_eq(fm.name, None)
  assert_eq(fm.platforms, ([] : Array[String]))
}

test "parse requires_tools from metadata block" {
  let content = "---\nname: foo\nmetadata:\n  hermes:\n    requires_tools: [kubectl]\n---\nbody\n"
  let fm = parse_frontmatter(content)
  assert_eq(fm.requires_tools, ["kubectl"])
}

test "parse tags from metadata.hermes" {
  let content = "---\nname: tagged-skill\ndescription: with tags\nmetadata:\n  hermes:\n    tags: [alpha, beta]\n---\nbody\n"
  let fm = parse_frontmatter(content)
  assert_eq(fm.tags, ["alpha", "beta"])
}

test "tags default to empty when absent" {
  let content = "---\nname: no-tags\n---\nbody\n"
  let fm = parse_frontmatter(content)
  assert_eq(fm.tags, ([] : Array[String]))
}