use crate::data::{Value, executable_query::ExecutableQuery};

pub struct InsertBuilder {
  table: String,
  columns: Vec<String>,
  returning: Vec<String>,
  values: Vec<Value>,
}

impl InsertBuilder {
  pub fn new(table: &str) -> Self {
    Self {
      table: table.to_string(),
      columns: Vec::new(),
      returning: Vec::new(),
      values: Vec::new(),
    }
  }

  pub fn column(mut self, column: &str, value: Value) -> Self {
    self.columns.push(column.to_string());
    self.values.push(value);
    self
  }

  pub fn returning(mut self, columns: &[&str]) -> Self {
    self.returning = columns.iter().map(|s| s.to_string()).collect();
    self
  }
}

impl ExecutableQuery for InsertBuilder {
  fn build(&self) -> (String, Vec<Value>) {
    if self.columns.is_empty() || self.values.is_empty() {
      panic!("Cannot build insert query without columns and values");
    }

    // Create the list of column names
    let columns = self.columns.join(", ");

    // Generate placeholders for values ($1, $2, etc.)
    let placeholders = (1..=self.values.len())
      .map(|i| format!("${}", i))
      .collect::<Vec<_>>()
      .join(", ");

    // Create the basic INSERT statement
    let mut query = format!(
      "INSERT INTO {} ({}) VALUES ({})",
      self.table, columns, placeholders
    );

    // Add RETURNING clause if specified
    if !self.returning.is_empty() {
      query.push_str(&format!(" RETURNING {}", self.returning.join(", ")));
    }

    (query, self.values.clone())
  }
}
