///|
/// List repositories under bhq root
pub fn hq_list(
  config : HqConfig,
  query : String?,
  /// List directories at path, returns (name, is_dir)
  list_dir : (String) -> Array[(String, Bool)],
  /// Check if path is a git repository
  is_git_repo : (String) -> Bool,
) -> Array[String] {
  let repos : Array[String] = []
  scan_repos(config.root, "", list_dir, is_git_repo, repos)
  // Filter by query if provided
  match query {
    Some(q) => repos.filter(path => path.contains(q))
    None => repos
  }
}

///|
fn scan_repos(
  root : String,
  rel_path : String,
  list_dir : (String) -> Array[(String, Bool)],
  is_git_repo : (String) -> Bool,
  repos : Array[String],
) -> Unit {
  let current_path = if rel_path.is_empty() {
    root
  } else {
    "\{root}/\{rel_path}"
  }
  // Check if current path is a git repo
  if is_git_repo(current_path) {
    repos.push(rel_path)
    return // Don't descend into git repos
  }
  // List and recurse into subdirectories
  let entries = list_dir(current_path)
  for entry in entries {
    let (name, is_dir) = entry
    if is_dir && !name.has_prefix(".") {
      let new_rel = if rel_path.is_empty() {
        name
      } else {
        "\{rel_path}/\{name}"
      }
      scan_repos(root, new_rel, list_dir, is_git_repo, repos)
    }
  }
}

///|
/// List repositories with full paths
pub fn hq_list_full_paths(
  config : HqConfig,
  query : String?,
  list_dir : (String) -> Array[(String, Bool)],
  is_git_repo : (String) -> Bool,
) -> Array[String] {
  hq_list(config, query, list_dir, is_git_repo).map(fn(rel) {
    "\{config.root}/\{rel}"
  })
}

///|
/// Parse a repository path back to RepoPath
pub fn parse_repo_path(rel_path : String) -> RepoPath? {
  let parts = rel_path.split("/").collect()
  // Check if first part looks like a host
  if parts.length() >= 3 && parts[0].to_owned().contains(".") {
    // host/user/repo
    let host = parts[0].to_owned()
    let normalized_host : String? = if host == "github.com" {
      None
    } else {
      Some(host)
    }
    Some(
      RepoPath::new(
        parts[1].to_owned(),
        parts[2].to_owned(),
        host=normalized_host,
      ),
    )
  } else if parts.length() >= 2 {
    // user/repo (github.com implicit)
    Some(RepoPath::new(parts[0].to_owned(), parts[1].to_owned()))
  } else {
    None
  }
}