/**
 * SQL Statement Generation Helpers
 * Provides utility functions for generating parameterized SQL INSERT and UPDATE statements.
 *
 * Author: Matthew Raymer
 */

/**
 * Generates SQL INSERT statement and parameters from a model object
 * @param model - The object to insert
 * @param tableName - The table name
 * @returns { sql, params } - SQL string and parameter array
 */
export function generateInsertStatement(
  model: Record<string, unknown>,
  tableName: string,
): { sql: string; params: unknown[] } {
  const columns = Object.keys(model).filter((key) => model[key] !== undefined);
  const values = Object.values(model)
    .filter((value) => value !== undefined)
    .map((value) => {
      if (value === null || value === undefined) return null;
      if (typeof value === "object" && value !== null) {
        return JSON.stringify(value);
      }
      if (typeof value === "boolean") return value ? 1 : 0;
      return value;
    });
  const placeholders = values.map(() => "?").join(", ");
  const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`;
  return { sql: insertSql, params: values };
}

/**
 * Generates SQL UPDATE statement and parameters from a model object
 * @param model - The object with fields to update
 * @param tableName - The table name
 * @param whereClause - The WHERE clause (e.g. "id = ?")
 * @param whereParams - Parameters for the WHERE clause
 * @returns { sql, params } - SQL string and parameter array
 */
export function generateUpdateStatement(
  model: Record<string, unknown>,
  tableName: string,
  whereClause: string,
  whereParams: unknown[] = [],
): { sql: string; params: unknown[] } {
  const setClauses: string[] = [];
  const params: unknown[] = [];
  Object.entries(model).forEach(([key, value]) => {
    setClauses.push(`${key} = ?`);
    let convertedValue = value ?? null;
    if (convertedValue !== null) {
      if (typeof convertedValue === "object") {
        convertedValue = JSON.stringify(convertedValue);
      } else if (typeof convertedValue === "boolean") {
        convertedValue = convertedValue ? 1 : 0;
      }
    }
    params.push(convertedValue);
  });
  if (setClauses.length === 0) {
    throw new Error("No valid fields to update");
  }
  const sql = `UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE ${whereClause}`;
  return { sql, params: [...params, ...whereParams] };
}
