///|
fn render_text_report(
  source_label : String,
  model : @trustflow.Model,
  findings : Array[@trustflow.Finding],
) -> Unit {
  println("MoonTrustFlow policy evaluation")
  println("source=\{source_label}")
  println(
    "nodes=\{model.nodes.length()}, edges=\{model.edges.length()}, policies=\{model.policies.length()}, findings=\{findings.length()}",
  )
  for finding in findings {
    println(@trustflow.format_finding(finding))
  }
}

///|
fn render_json_report(
  source_label : String,
  model : @trustflow.Model,
  findings : Array[@trustflow.Finding],
) -> Unit {
  let payload : Map[String, Json] = {
    "source": source_label.to_json(),
    "nodes": model.nodes.to_json(),
    "edges": model.edges.to_json(),
    "policies": model.policies.to_json(),
    "findings": findings.to_json(),
    "summary": {
      "node_count": model.nodes.length(),
      "edge_count": model.edges.length(),
      "policy_count": model.policies.length(),
      "finding_count": findings.length(),
    }.to_json(),
  }
  println(payload.to_json().stringify(indent=2))
}

///|
fn parse_cli_json_flag(args : Array[String]) -> Bool {
  for arg in args {
    if arg == "--json" || arg == "-j" {
      return true
    }
  }
  false
}

///|
fn parse_cli_flag(args : Array[String], name : String) -> Bool {
  for arg in args {
    if arg == name {
      return true
    }
  }
  false
}

///|
fn select_model_input() -> (String, String) {
  match @env.get_env_var("MOONTRUSTFLOW_MODEL_TEXT") {
    Some(model_text) if model_text != "" =>
      (
        model_text,
        match @env.get_env_var("MOONTRUSTFLOW_SOURCE_LABEL") {
          Some(label) if label != "" => label
          _ => "env:MOONTRUSTFLOW_MODEL_TEXT"
        },
      )
    _ => (@trustflow.sample_model_text(), "embedded-sample")
  }
}

///|
fn report_from_model(
  source_label : String,
  model : @trustflow.Model,
  mode : String,
) -> Unit {
  let findings = @trustflow.analyze(model)
  if mode == "sarif" {
    println(@trustflow.format_sarif(findings))
  } else if mode == "assessment" {
    println(@trustflow.format_assessment(@trustflow.assess_model(model)))
  } else if mode == "graph" {
    println(@trustflow.export_graph_text(model))
  } else if mode == "contract" {
    println(
      @trustflow.format_contract_report(
        @trustflow.evaluate_contract(model, @trustflow.default_model_contract()),
      ),
    )
  } else if mode == "json" {
    render_json_report(source_label, model, findings)
  } else {
    render_text_report(source_label, model, findings)
  }
}

///|
fn main {
  let args = @env.args()
  let mode = if parse_cli_flag(args, "--sarif") {
    "sarif"
  } else if parse_cli_flag(args, "--assessment") {
    "assessment"
  } else if parse_cli_flag(args, "--graph") {
    "graph"
  } else if parse_cli_flag(args, "--contract") {
    "contract"
  } else if parse_cli_json_flag(args) {
    "json"
  } else {
    "text"
  }
  let (model_text, source_label) = select_model_input()
  match @trustflow.parse_model(model_text) {
    Ok(model) => report_from_model(source_label, model, mode)
    Err(err) => {
      let message = @trustflow.format_error(err)
      if mode == "json" || mode == "sarif" {
        println(
          { "error": message, "source": source_label }
          .to_json()
          .stringify(indent=2),
        )
      } else {
        println("model error: " + message)
      }
    }
  }
}