import { _tag, _setTags, _getTags, _redact, _removeTag, _removeAllTags } from "agency-lang/stdlib-lib/tag.js"

/** @module
@summary Tag values and redact them in state logs.

```ts
import { redact } from "std::tag"

def hideSecret(apiKey: string) {
  redact(apiKey)
}
```

`redact` replaces a tagged value with `[REDACTED]` in state logs.
Pass a label to choose a different marker.

Primitive tags follow equal values: tagging one "secret" tags other equal
strings in the branch. Object and array tags follow their references,
so two objects with equal fields can have different tags.

Tags on primitives, extensible plain objects, and arrays survive forks and
checkpoint resume. Other objects, including ones already frozen when tagged,
use branch-local storage. Tags do not appear in ordinary JSON output.
*/

export def tag(value: any, key: string, val: any = true): any {
  """
  Attach a tag to a value and return its current tags.
  Primitives share tags by value; objects use reference identity.
  """
  return _tag(value, key, val)
}

export def setTags(value: any, tags: any): any {
  """
  Attach the entries of a tag object to a value and return its current tags.
  """
  return _setTags(value, tags)
}

/** The returned object is a shallow copy; nested tag values remain shared. */
export def getTags(value: any): any {
  """
  Return a value's tags, or an empty object if it has none.
  """
  return _getTags(value)
}

export def redact(value: any, label: string = ""): any {
  """
  Mark a value for replacement in state logs and return its current tags.

  @param label - Replacement text, or "" for "[REDACTED]".
  """
  const replacement = if label == "" then null else label
  return _redact(value, replacement)
}

export def removeTag(value: any, key: string): any {
  """Remove a single tag from a value. Returns the value's remaining tags."""
  return _removeTag(value, key)
}

export def removeAllTags(value: any): any {
  """Remove all tags from a value. Returns an empty object."""
  return _removeAllTags(value)
}
