///|
pub struct Scenario {
  name : String
  request : WebhookRequest
  expect_ok : Bool
  expected_route : String
} derive(Eq, Debug)

///|
pub fn Scenario::new(
  name : String,
  request : WebhookRequest,
  expect_ok : Bool,
  expected_route : String,
) -> Scenario {
  { name, request, expect_ok, expected_route }
}

///|
pub fn valid_github_issue_scenario() -> Scenario {
  Scenario::new(
    "valid_github_issue",
    example_github_request(),
    true,
    "handle_github_issues",
  )
}

///|
pub fn bad_signature_scenario() -> Scenario {
  Scenario::new("bad_signature", bad_signature_request(), false, "")
}

///|
pub fn expired_scenario() -> Scenario {
  Scenario::new("expired", expired_request(), false, "")
}

///|
pub fn feishu_message_scenario() -> Scenario {
  Scenario::new(
    "feishu_message",
    feishu_request(),
    true,
    "handle_feishu_message",
  )
}

///|
pub fn scenario_suite() -> Array[Scenario] {
  [
    valid_github_issue_scenario(),
    bad_signature_scenario(),
    expired_scenario(),
    feishu_message_scenario(),
  ]
}

///|
pub struct ScenarioResult {
  name : String
  passed : Bool
  detail : String
} derive(Eq, Debug)

///|
pub fn run_scenario(
  scenario : Scenario,
  config : GuardConfig,
) -> ScenarioResult {
  let scenario_config = if scenario.request.provider ==
    config.policy.provider.name {
    config
  } else {
    GuardConfig::for_provider(
      scenario.request.provider,
      "demo-secret",
      config.policy.now,
    )
  }
  let output = run_guard_pipeline(scenario.request, scenario_config)
  let ok_matches = output.verification.is_ok() == scenario.expect_ok
  let route_matches = if scenario.expected_route == "" {
    true
  } else {
    output.route.handler == scenario.expected_route
  }
  let passed = ok_matches && route_matches
  let detail = if passed { "passed" } else { pipeline_output_text(output) }
  { name: scenario.name, passed, detail }
}

///|
pub fn run_scenarios(
  scenarios : Array[Scenario],
  config : GuardConfig,
) -> Array[ScenarioResult] {
  Array::makei(scenarios.length(), i => run_scenario(scenarios[i], config))
}

///|
pub fn scenario_pass_count(results : Array[ScenarioResult]) -> Int {
  let mut count = 0
  for i in 0.. String {
  let builder = StringBuilder::new()
  builder.write_string("| scenario | passed | detail |\n")
  builder.write_string("| --- | --- | --- |\n")
  for i in 0..