// main.mbt — command-line interface (mirrors Python `cli.py` + `__main__.py`)
//
// Usage:
//   moon run cmd/main -- remember "内容" [--type preference] [--source s] [--no-interactive] [--conflict-policy keep]
//   moon run cmd/main -- recall "查询" [--top-k 5]
//   moon run cmd/main -- evolve
//   moon run cmd/main -- stats
//   moon run cmd/main -- list
// Common: [--root ] [--passphrase ]

///|
let _COMMANDS : Array[String] = [
  "remember", "recall", "evolve", "stats", "list",
]

///|
fn is_command(s : String) -> Bool {
  for c in _COMMANDS {
    if c == s {
      return true
    }
  }
  false
}

///|
fn parse_int_or(s : String, d : Int) -> Int {
  @string.parse_int(s) catch {
    _ => d
  }
}

// Substring check delegates to String::contains.

///|
fn str_has(s : String, sub : String) -> Bool {
  s.contains(sub)
}

///|
fn join_spaces(parts : Array[String]) -> String {
  let mut s = ""
  let mut first = true
  for p in parts {
    if first {
      s = p
      first = false
    } else {
      s = s + " " + p
    }
  }
  s
}

///|
fn print_json(j : Json) -> Unit {
  println(j.stringify(indent=2))
}

///|
fn run_cmd(
  sys : @oc.MemorySystem,
  cmd : String,
  rest : Array[String],
  mtype : String,
  source : String,
  no_interactive : Bool,
  conflict_policy : String,
  top_k : Int,
) -> Unit raise @fs.IOError {
  match cmd {
    "remember" => {
      let content = join_spaces(rest)
      let res = sys.remember(
        content,
        type_hint=mtype,
        source~,
        interactive=!no_interactive,
        conflict_policy~,
      )
      print_json(Json::object(res))
    }
    "recall" => {
      let query = join_spaces(rest)
      let res = sys.recall(query, top_k~)
      print_json(Json::array(res))
    }
    "evolve" => print_json(Json::object(sys.evolve()))
    "stats" => print_json(Json::object(sys.stats()))
    "list" => print_json(Json::array(sys.list_all()))
    _ => println("未知命令: " + cmd)
  }
}

///|
fn main {
  let all = @env.args()
  // Under the JS backend, args are [node, script.js, ...real args]; strip those.
  let args = if all.length() >= 2 && str_has(all[0], "node") {
    all.view(start=2).to_owned()
  } else {
    all
  }
  let mut root = "memory"
  let mut passphrase = ""
  let mut mtype = ""
  let mut source = "user_input"
  let mut no_interactive = false
  let mut top_k = 5
  let mut conflict_policy = "ask"
  let positional : Array[String] = []
  let mut i = 0
  while i < args.length() {
    let a = args[i]
    if a == "--root" {
      root = args[i + 1]
      i = i + 2
    } else if a == "--passphrase" {
      passphrase = args[i + 1]
      i = i + 2
    } else if a == "--type" {
      mtype = args[i + 1]
      i = i + 2
    } else if a == "--source" {
      source = args[i + 1]
      i = i + 2
    } else if a == "--top-k" {
      top_k = parse_int_or(args[i + 1], 5)
      i = i + 2
    } else if a == "--conflict-policy" {
      conflict_policy = args[i + 1]
      i = i + 2
    } else if a == "--no-interactive" {
      no_interactive = true
      i = i + 1
    } else {
      positional.push(a)
      i = i + 1
    }
  }
  // Find the command (skip a possible program-name element at position 0).
  let cmd_idx = if positional.length() > 0 && is_command(positional[0]) {
    0
  } else if positional.length() > 1 && is_command(positional[1]) {
    1
  } else {
    -1
  }
  if cmd_idx < 0 {
    println(
      "用法:  [text] [--root DIR] [--passphrase SECRET] [--type T] [--source S] [--top-k K] [--no-interactive] [--conflict-policy POLICY]",
    )
    return
  }
  let cmd = positional[cmd_idx]
  let rest = positional.view(start=cmd_idx + 1).to_owned()
  let sys = @oc.MemorySystem::new(root, passphrase~)
  run_cmd(sys, cmd, rest, mtype, source, no_interactive, conflict_policy, top_k) catch {
    _ => println("错误: 运行失败")
  }
}