///|
/// A small but realistic customer-support workflow.
///
/// The example models the operational states found in a help-desk system:
/// triage, assignment, customer waiting, escalation, resolution, reopening,
/// and cancellation. Context actions retain the facts an operator needs for
/// audit and service-level reporting.
struct TicketContext {
  ticket_id : String
  priority : Int
  updates : Int
  escalations : Int
  customer_replies : Int
  elapsed_steps : Int
  customer_notified : Bool
}

///|
fn initial_ticket(id : String, priority : Int) -> TicketContext {
  {
    ticket_id: id,
    priority,
    updates: 0,
    escalations: 0,
    customer_replies: 0,
    elapsed_steps: 0,
    customer_notified: false,
  }
}

///|
fn tick(ctx : TicketContext) -> TicketContext {
  {
    ticket_id: ctx.ticket_id,
    priority: ctx.priority,
    updates: ctx.updates,
    escalations: ctx.escalations,
    customer_replies: ctx.customer_replies,
    elapsed_steps: ctx.elapsed_steps + 1,
    customer_notified: ctx.customer_notified,
  }
}

///|
fn mark_update(ctx : TicketContext) -> TicketContext {
  let next = tick(ctx)
  {
    ticket_id: next.ticket_id,
    priority: next.priority,
    updates: next.updates + 1,
    escalations: next.escalations,
    customer_replies: next.customer_replies,
    elapsed_steps: next.elapsed_steps,
    customer_notified: true,
  }
}

///|
fn mark_reply(ctx : TicketContext) -> TicketContext {
  let next = tick(ctx)
  {
    ticket_id: next.ticket_id,
    priority: next.priority,
    updates: next.updates,
    escalations: next.escalations,
    customer_replies: next.customer_replies + 1,
    elapsed_steps: next.elapsed_steps,
    customer_notified: next.customer_notified,
  }
}

///|
fn mark_escalation(ctx : TicketContext) -> TicketContext {
  let next = mark_update(ctx)
  {
    ticket_id: next.ticket_id,
    priority: next.priority,
    updates: next.updates,
    escalations: next.escalations + 1,
    customer_replies: next.customer_replies,
    elapsed_steps: next.elapsed_steps,
    customer_notified: next.customer_notified,
  }
}

///|
fn support_builder() -> @fsm.Builder[String, String, TicketContext] {
  @fsm.Builder::new()
  .transition_do("Open", "Triage", "Triaged", fn(_s, _e, ctx) {
    mark_update(ctx)
  })
  .transition_if("Triaged", "Assign", "InProgress", fn(_s, _e, ctx) {
    ctx.priority > 0
  })
  .transition_do("InProgress", "RequestInfo", "WaitingCustomer", fn(
    _s,
    _e,
    ctx,
  ) {
    mark_update(ctx)
  })
  .transition_do("WaitingCustomer", "CustomerReply", "InProgress", fn(
    _s,
    _e,
    ctx,
  ) {
    mark_reply(ctx)
  })
  .transition_if("InProgress", "Resolve", "Resolved", fn(_s, _e, ctx) {
    ctx.updates > 0 && ctx.customer_replies >= 0
  })
  .transition_do("InProgress", "Escalate", "Escalated", fn(_s, _e, ctx) {
    mark_escalation(ctx)
  })
  .transition_if("Escalated", "Resolve", "Resolved", fn(_s, _e, ctx) {
    ctx.escalations > 0
  })
  .transition("Resolved", "Close", "Closed")
  .transition_do("Resolved", "Reopen", "InProgress", fn(_s, _e, ctx) {
    tick(ctx)
  })
  .transition("Open", "Cancel", "Cancelled")
  .transition("Triaged", "Cancel", "Cancelled")
  .transition("InProgress", "Cancel", "Cancelled")
}

///|
fn print_context(label : String, context : TicketContext) -> Unit {
  println(
    "\{label}: ticket=\{context.ticket_id}, updates=\{context.updates}, " +
    "replies=\{context.customer_replies}, escalations=\{context.escalations}, " +
    "elapsed=\{context.elapsed_steps}, notified=\{context.customer_notified}",
  )
}

///|
fn run_normal_path(
  builder : @fsm.Builder[String, String, TicketContext],
) -> Unit {
  let engine = builder.build("Open", initial_ticket("SUP-1001", 2))
  let report = engine.try_send_all([
    "Triage", "Assign", "RequestInfo", "CustomerReply", "Resolve", "Close",
  ])
  println(
    "Normal ticket: state=\{engine.state()}, accepted=\{report.successful}, " +
    "rejected=\{report.rejected}",
  )
  print_context("Normal context", engine.context())
  let summary = @fsm.history_summary(engine.history())
  println(
    "Normal audit: transitions=\{summary.transitions}, " +
    "guarded=\{summary.guarded_transitions}, actions=\{summary.action_transitions}",
  )
}

///|
fn run_escalation_path(
  builder : @fsm.Builder[String, String, TicketContext],
) -> Unit {
  let engine = builder.build("Open", initial_ticket("SUP-1002", 3))
  let report = engine.try_send_all([
    "Triage", "Assign", "Escalate", "Resolve", "Reopen", "RequestInfo", "CustomerReply",
    "Resolve", "Close",
  ])
  println(
    "Escalation path: state=\{engine.state()}, accepted=\{report.successful}, " +
    "rejected=\{report.rejected}",
  )
  print_context("Escalation context", engine.context())
  let graph = @fsm.graph_summary(builder, "Open")
  println(
    "Graph review: states=\{graph.state_count}, transitions=\{graph.transition_count}, " +
    "branches=\{graph.branching_states.length()}, cycle=\{graph.has_cycle}",
  )
}

///|
fn run_budget_path(
  builder : @fsm.Builder[String, String, TicketContext],
) -> Unit {
  let engine = builder.build("Open", initial_ticket("SUP-1003", 1))
  let report = engine.try_send_with_budget(
    ["Resolve", "Assign", "Triage", "Assign", "Resolve"],
    1,
  )
  println(
    "Budget path: processed=\{report.processed}, accepted=\{report.successful}, " +
    "rejected=\{report.rejected}, stopped=\{report.stopped}",
  )
  print_context("Budget context", engine.context())
}

///|
fn main {
  println("--- Support Ticket Workflow Example ---")
  let builder = support_builder()
  run_normal_path(builder)
  run_escalation_path(builder)
  run_budget_path(builder)
  let score = @fsm.workflow_risk_score(builder, "Open")
  println("Risk score: \{score}")
  println("Mermaid Diagram:\n" + @fsm.to_mermaid(builder))
}