import {
  _args,
  _cwd,
  _env,
  _setEnv,
  _exit,
  _openUrl,
  _screenshot,
  _isTTY,
  _readStdin,
  _setTitle,
 } from "agency-lang/stdlib-lib/system.js"
import { _notify } from "agency-lang/stdlib-lib/builtins.js"

/** @module Talk to the host OS: read command-line args and environment
variables, find the current directory, show notifications, take screenshots,
open URLs, and read from stdin.

  ```ts
  import { args, env, notify } from "std::system"

  node main() {
    const home = env("HOME")
    notify("Done", "Processed ${args().length} arguments")
  }
  ```
*/

effect std::screenshot { filepath: string }
effect std::exit { code: number }
effect std::setEnv { name: string, value: string }
effect std::openUrl { url: string }
effect std::notify { title: string, body: string }

export def notify(title: string, message: string): boolean {
  """
  Show a native OS notification. Returns true if the notification was sent.

  @param title - The notification title
  @param message - The notification body text
  """
  return interrupt std::notify("Are you sure you want to show this notification?", {
    title: title,
    body: message
  })
  return _notify(title, message)
}

/** Ctrl-C, a race loss, or a time-guard abort interrupts an in-progress
screencapture. */
export def screenshot(
  filepath: string,
  x: number = -1,
  y: number = -1,
  width: number = -1,
  height: number = -1,
  allowedPaths: string[] = [],
) {
  """
  Take a screenshot and save it to a file. Pass x, y, width, and height to capture a specific region.

  @param filepath - Path to save the screenshot
  @param x - X coordinate of the capture region; -1 for the full screen
  @param y - Y coordinate of the capture region; -1 for the full screen
  @param width - Width of the capture region; -1 for the full screen
  @param height - Height of the capture region; -1 for the full screen
  @param allowedPaths - Only allow saving under these path prefixes
  """
  return interrupt std::screenshot("Are you sure you want to take a screenshot? This will capture the screen contents, which may include sensitive information.", {
    filepath: filepath
  })

  _screenshot(filepath, x, y, width, height, allowedPaths)
}

export def exit(code: number = 0) {
  """
  Terminate the process immediately with the given exit code. Use with caution. This skips any cleanup or pending operations.
  @param code - Exit code (0 for success, non-zero for failure)
  """
  return interrupt std::exit("Are you sure you want to exit the process?", {
    code: code
  })
  _exit(code)
}

export def args(): string[] {
  """
  Return the command-line arguments passed to the Agency program (excluding the node executable and script path).
  """
  return _args()
}

export def cwd(): string {
  """
  Return the absolute path of the current working directory of the Agency process.
  """
  return _cwd()
}

export def env(name: string): string | null {
  """
  Read an environment variable. Returns null if the variable is not set.
  """
  return _env(name)
}

export def setEnv(name: string, value: string): Result {
  """
  Set an environment variable in the current process. Fails if the name is empty or contains '='. The change is visible to child processes spawned afterward but does not persist outside the current process.

  @param name - The environment variable name
  @param value - The value to set
  """
  return interrupt std::setEnv("Are you sure you want to set this environment variable?", {
    name: name,
    value: value
  })
  return try _setEnv(name, value)
}

export def isTTY(): boolean {
  """
  Return true if standard input is connected to a terminal. Returns false when stdin is piped or redirected from a file. Use this to detect non-interactive invocations (e.g. `echo "hi" | my-agent`) and adjust output accordingly.
  """
  return _isTTY()
}

export def readStdin(): string {
  """
  Read all of standard input until EOF and return it as a string. Blocks until the input stream closes. Intended for non-interactive invocations where the user pipes input into the program.
  """
  return _readStdin()
}

/** macOS-only. Ctrl-C, a race loss, or a time-guard abort kills the in-flight
`open` subprocess. */
export def openUrl(url: string): Result {
  """
  Open a URL in the user's default browser.

  @param url - The URL to open
  """
  return interrupt std::openUrl("Are you sure you want to open this URL in the browser?", {
    url: url
  })

  return try _openUrl(url)
}

export def setTitle(title: string): void {
  """
  Set the process title (as shown in system monitors, `ps` output, and the terminal window). This can help users identify the process, especially when running multiple agents simultaneously.

  @param title - The new process title
  """
  return _setTitle(title)
}
