# Module: User Interface Utilities
# Purpose: Provides terminal UI utilities: output formatting, prompts, spinners, and status displays.
# Dependencies: error for error handling, logging for debug utilities

use ../config/accessor.nu *
use logging.nu [is-debug-enabled]

# Check if no-terminal mode is enabled
export def get-provisioning-no-terminal [] {
    # Check environment variable first (use -o for optional in Nushell 0.106+)
    let env_no_terminal = ($env | get -o PROVISIONING_NO_TERMINAL | default "false")
    if ($env_no_terminal == "true") or ($env_no_terminal == "1") {
        return true
    }

    # Check config setting
    config-get "debug.no_terminal" false
}

# Get output format (json, yaml, table, etc.)
export def get-provisioning-out [] {
    # Check environment variable first
    let env_out = ($env | get -o PROVISIONING_OUT | default "")
    if ($env_out | is-not-empty) {
        return $env_out
    }

    # Check config setting
    config-get "output.format" ""
}

# Set no-terminal mode
export def set-provisioning-no-terminal [value: bool] {
    $env.PROVISIONING_NO_TERMINAL = $value
}

# Set output format
export def set-provisioning-out [value: string] {
    $env.PROVISIONING_OUT = $value
}

# Get notification icon path
export def get-notify-icon [] : nothing -> string {
    $env.PROVISIONING_NOTIFY_ICON? | default ""
}

export def _ansi [
  arg?: string
  --escape: record
] {
  if (get-provisioning-no-terminal) {
    ""
  } else if (is-terminal --stdout) {
    if $escape != null {
      (ansi --escape $escape)
    } else if ($arg != null) and ($arg != "") {
      (ansi $arg)
    } else {
      ""
    }
  } else {
    ""
  }
}
export def format_out [
  data: string
  src?: string
  mode?: string
] {
  let msg = match $src {
    "json" => ($data | from json),
    _ => $data,
  }
  match $mode {
    "table" => {
      ($msg | table -i false)
    },
    _ => { $msg }
  }
}
export def _print [
  data: string
  src?: string
  context?: string
  mode?: string
  -n    # no newline
] {
  let output = (get-provisioning-out)
  if $n {
    if ($output | is-empty)  {
      print -n $data
    }
    return
  }
  if ($output | is-empty)  {
    print (format_out $data $src $mode)
  } else {
    match $output {
       "json" => {
          if $context != "result" { return }
          if $src == "json" {
            print ($data)
          } else {
            print ($data | to json)
          }
       },
       "yaml" | "yml" => {
          if $context != "result" { return }
          if $src == "json" {
            print ($data | from json | to yaml)
          } else {
            print ($data | to yaml)
          }
       },
       "toml" | "tml" => {
          if $context != "result" { return }
          if $src == "json" {
            print ($data | from json | to toml)
          } else {
            print ($data)
          }
       },
       "text" | "txt" => {
          if $context != "result" { return }
          print (format_out $data $src $mode)
       },
       _ => {
        if ($output | str ends-with ".json" ) {
          if $context != "result" { return }
          (if $src == "json" {
            ($data)
          } else {
            ($data | to json)
          } |  save --force $output)
        } else if ($output | str ends-with ".yaml" ) {
          if $context != "result" { return }
          (if $src == "json" {
            ($data | from json | to yaml)
          } else {
            ($data | to yaml)
          } | save --force $output)
        } else if ($output | str ends-with ".toml" ) {
          if $context != "result" { return }
          (if $src == "json" {
            ($data | from json | to toml)
          } else {
            ($data)
          } | save --force $output)
        } else if ($output | str ends-with ".text" ) or ($output | str ends-with ".txt" ) {
          if $context != "result" { return }
          format_out $data $src $mode | save --force $output
        } else {
          format_out $data $src $mode | save --append $output
        }
      }
    }
  }
}
export def end_run  [
  context: string
] {
  if ($env.PROVISIONING_OUT? | default "" | is-not-empty) { return }
  if ($env.PROVISIONING_NO_TITLES? | default false) { return }
  if (detect_claude_code) { return }
  if (is-debug-enabled) {
    _print $"\n(_ansi blue)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)"
  } else {
    let the_context = if $context != "" { $"  to ($context)" } else { "" }
    if (is-terminal --stdout) {
      _print $"\n(_ansi cyan)Thanks for using (_ansi blue_bold)((get-provisioning-url) | ansi link --text 'Provisioning')(_ansi reset)"
      if $the_context != "" {
        _print  $"(_ansi yellow_dimmed)($the_context)(_ansi reset)"
      }
      _print ((get-provisioning-url) | ansi link --text $"(_ansi default_dimmed)Click here for more info or visit \n((get-provisioning-url))(_ansi reset)")
    } else {
      _print $"\n(_ansi cyan)Thanks for using (_ansi blue_bold) Provisioning [((get-provisioning-url))](_ansi reset)($the_context)"
      _print $"(_ansi default_dimmed)For more info or visit ((get-provisioning-url))(_ansi reset)"

    }
  }
}

export def show_clip_to  [
  msg: string
  show: bool
] {
  if $show { _print $msg }
  if (is-terminal --stdout) {
    if ((version).installed_plugins | str contains "clipboard") {
      $msg | clipboard copy
      print $"(ansi default_dimmed)copied into clipboard now (ansi reset)"
    }
  }
}

export def log_debug [
   msg: string
] {
   use std
   std log debug $msg
   # std assert (1 == 1)
}

#// Examples:
#// desktop_run_notify "Port scan" "Done" { port scan 8.8.8.8 53 }
#// desktop_run_notify "Task try" "Done" --timeout 5sec
export def desktop_run_notify [
  title: string
  body: string
  task?: closure
  --timeout: duration
  --icon: string
] {
  let icon_path = if $icon == null {
    (get-notify-icon)
  } else { $icon }
  let time_out = if $timeout == null {
    8sec
  } else { $timeout }
  if $task != null {
    let start = date now
    let result = do $task
    let end = date now
    let total = $end - $start | format duration sec
    let result_typ = ($result | describe)
    let msg = if $result_typ == "bool" {
      (if $result { "✅ done " } else { $"🛑 fail "})
    } else if ($result_typ | str starts-with  "record") {
      (if $result.status { "✅ done " } else { $"🛑 fail ($result.error)" })
    } else { "" }
    let time_body = $"($body) ($msg) finished in ($total) "
    if ((version).installed_plugins | str contains "desktop_notifications") {
      notify -s $title -t $time_body --timeout $time_out -i $icon_path
    } else {
      _print $"(_ansi blue)($title)(_ansi reset)\n(_ansi blue_bold)($time_body)(_ansi reset)"
    }
    return $result
  } else {
    if ((version).installed_plugins | str contains "desktop_notifications") {
      notify -s $title -t $body --timeout $time_out -i $icon_path
    } else {
      _print $"(_ansi blue)($title)(_ansi reset)\n(_ansi blue_bold)($body)(_ansi reset)"
    }
    true
  }
}

export def detect_claude_code [] {
    let claudecode = ($env.CLAUDECODE? | default "" | str contains "1")
    let entrypoint = ($env.CLAUDE_CODE_ENTRYPOINT? | default "" | str contains "cli")
    $claudecode or $entrypoint
}
