// UpdateBuilder — fluent builder for UPDATE statements, with type-state.
//
// Type-state via separate types:
//   Table::update()           → UpdateBuilder  (pending — no WHERE yet)
//   UpdateBuilder::where_(..) → UpdateReady    (ready — can call to_sql)

///|
/// A pending UPDATE builder.  Must call `.where_()` before `.to_sql()`.
pub(all) struct UpdateBuilder {
  table : Table
  set_clauses : Array[@ast.SetClause]
}

///|
/// A complete UPDATE builder with a WHERE clause.  Terminal: `.to_sql()`.
pub(all) struct UpdateReady {
  table : Table
  set_clauses : Array[@ast.SetClause]
  where_clause : @ast.Expr
  returning : Array[@ast.ColumnRef]?
}

///|
/// Create a new UpdateBuilder.  Internal — users call `table.update()`.
pub fn UpdateBuilder::new(table : Table) -> UpdateBuilder {
  UpdateBuilder::{ table, set_clauses: [] }
}

///|
/// Add a SET clause.  Column as &AnyColumn, value as &@moonpg.ToValue.
pub fn UpdateBuilder::set(
  self : UpdateBuilder,
  column : &AnyColumn,
  value : &@moonpg.ToValue,
) -> UpdateBuilder {
  self.set_clauses.push(@ast.SetClause::{ column: column.to_ref(), value })
  self
}

///|
/// Attach a WHERE clause.  Promotes to UpdateReady.
pub fn UpdateBuilder::where_(
  self : UpdateBuilder,
  condition : @ast.Filter,
) -> UpdateReady {
  UpdateReady::{
    table: self.table,
    set_clauses: self.set_clauses,
    where_clause: condition,
    returning: None,
  }
}

///|
/// Attach another WHERE condition, AND-ed with the existing one.
pub fn UpdateReady::where_(
  self : UpdateReady,
  condition : @ast.Filter,
) -> UpdateReady {
  UpdateReady::{ ..self, where_clause: self.where_clause.and_(condition) }
}

///|
/// Attach a RETURNING clause.
pub fn UpdateReady::returning(
  self : UpdateReady,
  cols : Array[&AnyColumn],
) -> UpdateReady {
  UpdateReady::{ ..self, returning: Some(cols.map(c => c.to_ref())) }
}

///|
/// Render the query to a parameterised SQL string + args array.
pub fn UpdateReady::to_sql(
  self : UpdateReady,
) -> (String, Array[&@moonpg.ToValue]) {
  let node = @ast.UpdateStmt::{
    table: self.table.qualified_name(),
    set_clauses: self.set_clauses,
    where_clause: self.where_clause,
    returning: self.returning,
  }
  @tosql.update_stmt_to_sql(node)
}