///|
/// Output format selected by the command-line interface.
pub(all) enum OutputFormat {
  Text
  Json
  Sarif
} derive(Debug, Eq)

///|
pub fn OutputFormat::label(self : OutputFormat) -> String {
  match self {
    Text => "text"
    Json => "json"
    Sarif => "sarif"
  }
}

///|
/// Parsed Moon Doctor command-line options.
pub(all) struct CliOptions {
  target : String
  format : OutputFormat
  strict : Bool
  help : Bool
} derive(Debug, Eq)

///|
fn parse_format(value : String) -> OutputFormat? {
  match value {
    "text" => Some(Text)
    "json" => Some(Json)
    "sarif" => Some(Sarif)
    _ => None
  }
}

///|
fn parse_options_at(
  args : Array[String],
  index : Int,
  format : OutputFormat,
  strict : Bool,
  target : String?,
  help : Bool,
) -> Result[CliOptions, String] {
  if index >= args.length() {
    let resolved_target = match target {
      Some(value) => value
      None => "."
    }
    return Ok({ target: resolved_target, format, strict, help })
  }
  let arg = args[index]
  match arg {
    "--help" | "-h" =>
      parse_options_at(args, index + 1, format, strict, target, true)
    "--strict" => parse_options_at(args, index + 1, format, true, target, help)
    "--format" =>
      if index + 1 >= args.length() {
        Err("--format requires text or json")
      } else {
        match parse_format(args[index + 1]) {
          Some(next_format) =>
            parse_options_at(args, index + 2, next_format, strict, target, help)
          None => Err("unsupported format: " + args[index + 1])
        }
      }
    _ =>
      if arg.has_prefix("-") {
        Err("unsupported option: " + arg)
      } else {
        match target {
          None =>
            parse_options_at(args, index + 1, format, strict, Some(arg), help)
          Some(_) => Err("only one project path is supported")
        }
      }
  }
}

///|
/// Parse process arguments, including the executable name at index zero.
pub fn parse_cli_args(args : Array[String]) -> Result[CliOptions, String] {
  parse_options_at(args, 1, Text, false, None, false)
}

///|
/// Return the stable command-line usage text.
pub fn cli_usage() -> String {
  let usage =
    #|Usage: moon run cmd/main -- [--format text|json] [--strict] [path]
    #|
    #|Check a MoonBit project directory. The default path is the current directory.
    #|
    #|Options:
    #|  --format text|json  Select a human-readable or machine-readable report.
    #|  --strict            Exit with failure when ERROR or WARN diagnostics exist.
    #|  -h, --help          Show this help text.
    #|
  usage
}

///|
/// Strict mode blocks release workflows on errors and warnings, not INFO advice.
pub fn should_fail_strict(options : CliOptions, report : DoctorReport) -> Bool {
  options.strict && (report.score.errors > 0 || report.score.warnings > 0)
}