///|
/// Entry point for the CLI program.
fn main {
  let argv = @env.args()

  if argv.length() < 3 {
    print_usage()
    return
  }

  let dir = argv[1]
  let cmd = argv[2]

  // Set default maximum file size to 10MB
  let max_file_size = 10 * 1024 * 1024

  try {
    let db = @moonkv.DB::open(dir, max_file_size)

    if cmd == "put" {
      if argv.length() < 5 {
        println("Error: put command requires key and value arguments.")
        println("Usage: moon run cmd/main --  put  ")
        return
      }
      let key = argv[3]
      let value_str = argv[4]
      let value = @moonkv.string_to_bytes(value_str)
      db.put(key, value)
      println("OK")
    } else if cmd == "put-ttl" {
      if argv.length() < 6 {
        println(
          "Error: put-ttl command requires key, value, and ttl arguments.",
        )
        println(
          "Usage: moon run cmd/main --  put-ttl   ",
        )
        return
      }
      let key = argv[3]
      let value_str = argv[4]
      let value = @moonkv.string_to_bytes(value_str)
      let ttl = parse_int64(argv[5])
      db.put_ttl(key, value, ttl)
      println("OK")
    } else if cmd == "get" {
      if argv.length() < 4 {
        println("Error: get command requires key argument.")
        println("Usage: moon run cmd/main --  get ")
        return
      }
      let key = argv[3]
      let val = db.get(key)
      println(@moonkv.bytes_to_string(val))
    } else if cmd == "delete" {
      if argv.length() < 4 {
        println("Error: delete command requires key argument.")
        println("Usage: moon run cmd/main --  delete ")
        return
      }
      let key = argv[3]
      db.delete(key)
      println("OK")
    } else if cmd == "delete-prefix" {
      if argv.length() < 5 {
        println(
          "Error: delete-prefix command requires prefix and limit arguments.",
        )
        println(
          "Usage: moon run cmd/main --  delete-prefix  ",
        )
        return
      }
      let deleted = db.delete_prefix(argv[3], parse_int(argv[4]))
      println("deleted=\{deleted}")
    } else if cmd == "merge" {
      db.merge()
      println("Compaction completed successfully.")
    } else if cmd == "scan" {
      if argv.length() < 5 {
        println("Error: scan command requires prefix and limit arguments.")
        println("Usage: moon run cmd/main --  scan  ")
        return
      }
      let prefix = argv[3]
      let limit = parse_int(argv[4])
      let rows = db.scan_prefix(prefix, limit)
      for row in rows {
        println("\{row.0}\t\{@moonkv.bytes_to_string(row.1)}")
      }
    } else if cmd == "stats" {
      let stats = db.stats()
      println("keys=\{stats.key_count}")
      println("live_value_bytes=\{stats.live_value_bytes}")
      println("active_file_id=\{stats.active_file_id}")
      println("active_file_offset=\{stats.active_file_offset}")
      println("max_file_size=\{stats.max_file_size}")
      println("logical_clock=\{stats.logical_clock}")
    } else if cmd == "verify" {
      let verified = db.verify()
      println("verified_keys=\{verified}")
    } else if cmd == "fingerprint" {
      println("fingerprint=\{db.fingerprint()}")
    } else {
      println("Unknown command: \{cmd}")
      print_usage()
    }

    db.close()
  } catch {
    @moonkv.MoonKVError::KeyNotFound(k) => println("Error: Key not found: \{k}")
    @moonkv.MoonKVError::IOError(msg) => println("IO Error: \{msg}")
    @moonkv.MoonKVError::CorruptedDatabase(msg) =>
      println("Corrupted Database: \{msg}")
    @moonkv.MoonKVError::InvalidRecord(msg) => println("Invalid Record: \{msg}")
  }
}

///|
/// Prints CLI usage instructions.
fn print_usage() -> Unit {
  println("moonkv - High-performance Log-Structured Key-Value Store in MoonBit")
  println("")
  println("Usage:")
  println("  moon run cmd/main --   [args]")
  println("")
  println("Commands:")
  println("  put              Write a key-value pair")
  println(
    "  put-ttl      Write a key-value pair with Time-To-Live (logical clocks)",
  )
  println("  get                     Retrieve the value of a key")
  println("  delete                  Delete a key")
  println(
    "  delete-prefix    Atomically delete up to n matching keys",
  )
  println("  merge                        Compact the database logs")
  println("  scan          Scan visible keys in sorted order")
  println("  stats                        Show key count and storage metadata")
  println("  verify                       Read and validate all visible values")
  println(
    "  fingerprint                 Print a deterministic keyspace fingerprint",
  )
}

///|
/// Basic 64-bit integer parser.
fn parse_int64(s : String) -> Int64 {
  let mut val = 0L
  let len = s.length()
  let mut start = 0
  let is_neg = if len > 0 && s[0] == '-' {
    start = 1
    true
  } else {
    false
  }
  for i = start; i < len; i = i + 1 {
    let ch = s[i]
    if ch >= '0' && ch <= '9' {
      let digit = (ch.to_int() - '0'.to_int()).to_int64()
      val = val * 10L + digit
    }
  }
  if is_neg {
    -val
  } else {
    val
  }
}

///|
/// Basic signed integer parser used by scan limits.
fn parse_int(s : String) -> Int {
  let mut val = 0
  let len = s.length()
  let mut start = 0
  let is_neg = if len > 0 && s[0] == '-' {
    start = 1
    true
  } else {
    false
  }
  for i = start; i < len; i = i + 1 {
    let ch = s[i]
    if ch >= '0' && ch <= '9' {
      val = val * 10 + ch.to_int() - '0'.to_int()
    }
  }
  if is_neg {
    -val
  } else {
    val
  }
}