function generateSelectQuery(entityConfig, options = {}) {
  const {
    select,
    where = [],
    orderBy = [],
    limit,
    offset,
    includeDeleted = false
  } = options;
  const selectFields = select || generateSelectFields(entityConfig);
  const selectClause = selectFields.join(", ");
  const tableName = entityConfig.slug;
  const fromClause = `FROM ${tableName}`;
  const whereConditions = [];
  const params = [];
  let paramIndex = 1;
  if (!includeDeleted) {
    whereConditions.push(`${tableName}.deleted_at IS NULL`);
  }
  where.forEach((condition, index) => {
    const connector = index > 0 && condition.connector ? condition.connector : "AND";
    const placeholder = `$${paramIndex++}`;
    const conditionSql = buildWhereCondition(condition, placeholder, tableName);
    if (whereConditions.length > 0) {
      whereConditions.push(`${connector} ${conditionSql}`);
    } else {
      whereConditions.push(conditionSql);
    }
    params.push(formatParamValue(condition.value, condition.operator));
  });
  const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" ")}` : "";
  const orderByConditions = orderBy.map((order) => {
    let orderClause = `${tableName}.${order.field} ${order.direction}`;
    if (order.nulls) {
      orderClause += ` NULLS ${order.nulls}`;
    }
    return orderClause;
  });
  if (orderByConditions.length === 0 && true) {
    orderByConditions.push(`${tableName}.created_at DESC`);
  }
  const orderByClause = orderByConditions.length > 0 ? `ORDER BY ${orderByConditions.join(", ")}` : "";
  let limitClause = "";
  if (limit) {
    limitClause = `LIMIT $${paramIndex++}`;
    params.push(limit);
    if (offset) {
      limitClause += ` OFFSET $${paramIndex++}`;
      params.push(offset);
    }
  }
  const sql = [
    `SELECT ${selectClause}`,
    fromClause,
    whereClause,
    orderByClause,
    limitClause
  ].filter(Boolean).join(" ");
  return {
    sql: sql.trim(),
    params,
    estimatedRows: limit || 1e3
  };
}
function generateInsertQuery(entityConfig, data, userId) {
  const tableName = entityConfig.slug;
  const insertableFields = getInsertableFields(entityConfig);
  const fields = [];
  const placeholders = [];
  const params = [];
  let paramIndex = 1;
  insertableFields.forEach((field) => {
    if (data.hasOwnProperty(field.name)) {
      fields.push(field.name);
      placeholders.push(`$${paramIndex++}`);
      params.push(formatFieldValue(data[field.name], field));
    }
  });
  if (true) {
    const now = (/* @__PURE__ */ new Date()).toISOString();
    fields.push("created_at", "updated_at");
    placeholders.push(`$${paramIndex++}`, `$${paramIndex++}`);
    params.push(now, now);
  }
  if (userId && !fields.includes("user_id")) {
    const hasUserField = entityConfig.fields.some((f) => f.name === "userId" || f.name === "user_id");
    if (hasUserField) {
      fields.push("user_id");
      placeholders.push(`$${paramIndex++}`);
      params.push(userId);
    }
  }
  const sql = `
    INSERT INTO ${tableName} (${fields.join(", ")})
    VALUES (${placeholders.join(", ")})
    RETURNING *
  `.trim();
  return { sql, params };
}
function generateUpdateQuery(entityConfig, id, data, userId) {
  const tableName = entityConfig.slug;
  const updatableFields = getUpdatableFields(entityConfig);
  const setConditions = [];
  const params = [];
  let paramIndex = 1;
  updatableFields.forEach((field) => {
    if (data.hasOwnProperty(field.name)) {
      setConditions.push(`${field.name} = $${paramIndex++}`);
      params.push(formatFieldValue(data[field.name], field));
    }
  });
  if (true) {
    setConditions.push(`updated_at = $${paramIndex++}`);
    params.push((/* @__PURE__ */ new Date()).toISOString());
  }
  if (userId) {
    const hasUpdatedByField = entityConfig.fields.some((f) => f.name === "updatedBy" || f.name === "updated_by");
    if (hasUpdatedByField) {
      setConditions.push(`updated_by = $${paramIndex++}`);
      params.push(userId);
    }
  }
  if (setConditions.length === 0) {
    throw new Error("No fields to update");
  }
  params.push(id);
  const sql = `
    UPDATE ${tableName}
    SET ${setConditions.join(", ")}
    WHERE ${"id"} = $${paramIndex}
    RETURNING *
  `.trim();
  return { sql, params };
}
function generateDeleteQuery(entityConfig, id, userId) {
  const tableName = entityConfig.slug;
  const params = [id];
  let paramIndex = 2;
  if (true) {
    const setConditions = [`deleted_at = $${paramIndex++}`];
    params.splice(1, 0, (/* @__PURE__ */ new Date()).toISOString());
    if (userId) {
      const hasDeletedByField = entityConfig.fields.some((f) => f.name === "deletedBy" || f.name === "deleted_by");
      if (hasDeletedByField) {
        setConditions.push(`deleted_by = $${paramIndex++}`);
        params.splice(-1, 0, userId);
      }
    }
    const sql = `
      UPDATE ${tableName}
      SET ${setConditions.join(", ")}
      WHERE ${"id"} = $${params.length}
      RETURNING *
    `.trim();
    return { sql, params };
  } else {
    const sql = `
      DELETE FROM ${tableName}
      WHERE ${"id"} = $1
      RETURNING *
    `.trim();
    return { sql, params };
  }
}
function generateChildEntityQueries(parentEntityConfig, parentId, childNames = "all") {
  const queries = {};
  if (!parentEntityConfig.childEntities) {
    return queries;
  }
  const childrenToQuery = childNames === "all" ? Object.keys(parentEntityConfig.childEntities) : childNames;
  childrenToQuery.forEach((childName) => {
    const childConfig = parentEntityConfig.childEntities[childName];
    if (childConfig) {
      queries[childName] = generateChildSelectQuery(
        parentEntityConfig.slug,
        childConfig,
        parentId
      );
    }
  });
  return queries;
}
function generateChildSelectQuery(parentEntityName, childConfig, parentId) {
  const tableName = childConfig.table;
  const selectFields = childConfig.fields.map((f) => f.name);
  const allFields = ["id", ...selectFields, "created_at", "updated_at"];
  const uniqueFields = [...new Set(allFields)];
  const sql = `
    SELECT ${uniqueFields.join(", ")}
    FROM ${tableName}
    WHERE ${parentEntityName}_id = $1
    AND deleted_at IS NULL
    ORDER BY created_at ASC
  `.trim();
  return {
    sql,
    params: [parentId]
  };
}
function generateChildInsertQuery(parentEntityName, childConfig, parentId, data, userId) {
  const tableName = childConfig.table;
  const fields = ["id", `${parentEntityName}_id`];
  const placeholders = ["gen_random_uuid()", "$1"];
  const params = [parentId];
  let paramIndex = 2;
  childConfig.fields.forEach((field) => {
    if (data.hasOwnProperty(field.name)) {
      fields.push(field.name);
      placeholders.push(`$${paramIndex++}`);
      const fieldValue = data[field.name];
      let formattedValue;
      if (fieldValue === null || fieldValue === void 0) {
        formattedValue = null;
      } else if (field.type === "json") {
        formattedValue = typeof fieldValue === "string" ? fieldValue : JSON.stringify(fieldValue);
      } else if (field.type === "boolean") {
        formattedValue = String(Boolean(fieldValue));
      } else {
        formattedValue = String(fieldValue);
      }
      params.push(formattedValue);
    }
  });
  const now = (/* @__PURE__ */ new Date()).toISOString();
  fields.push("created_at", "updated_at");
  placeholders.push(`$${paramIndex++}`, `$${paramIndex++}`);
  params.push(now, now);
  if (userId) {
    fields.push("created_by");
    placeholders.push(`$${paramIndex++}`);
    params.push(userId);
  }
  const sql = `
    INSERT INTO ${tableName} (${fields.join(", ")})
    VALUES (${placeholders.join(", ")})
    RETURNING *
  `.trim();
  return { sql, params };
}
function generateChildUpdateQuery(parentEntityName, childConfig, childId, data, userId) {
  const tableName = childConfig.table;
  const setConditions = [];
  const params = [];
  let paramIndex = 1;
  childConfig.fields.forEach((field) => {
    if (data.hasOwnProperty(field.name)) {
      setConditions.push(`${field.name} = $${paramIndex++}`);
      const fieldValue = data[field.name];
      let formattedValue;
      if (fieldValue === null || fieldValue === void 0) {
        formattedValue = null;
      } else if (field.type === "json") {
        formattedValue = typeof fieldValue === "string" ? fieldValue : JSON.stringify(fieldValue);
      } else if (field.type === "boolean") {
        formattedValue = String(Boolean(fieldValue));
      } else {
        formattedValue = String(fieldValue);
      }
      params.push(formattedValue);
    }
  });
  setConditions.push(`updated_at = $${paramIndex++}`);
  params.push((/* @__PURE__ */ new Date()).toISOString());
  if (userId) {
    setConditions.push(`updated_by = $${paramIndex++}`);
    params.push(userId);
  }
  params.push(childId);
  const sql = `
    UPDATE ${tableName}
    SET ${setConditions.join(", ")}
    WHERE id = $${paramIndex}
    AND deleted_at IS NULL
    RETURNING *
  `.trim();
  return { sql, params };
}
function generateChildDeleteQuery(childConfig, childId, userId) {
  const tableName = childConfig.table;
  const params = [(/* @__PURE__ */ new Date()).toISOString(), childId];
  let sql = `
    UPDATE ${tableName}
    SET deleted_at = $1
    WHERE id = $2
    RETURNING *
  `.trim();
  if (userId) {
    sql = `
      UPDATE ${tableName}
      SET deleted_at = $1, deleted_by = $3
      WHERE id = $2
      RETURNING *
    `.trim();
    params.splice(1, 0, userId);
  }
  return { sql, params };
}
function generateBulkQueries(entityConfig, operations, userId) {
  return operations.map((op) => {
    switch (op.type) {
      case "insert":
        return generateInsertQuery(entityConfig, op.data, userId);
      case "update":
        return generateUpdateQuery(entityConfig, op.id, op.data, userId);
      case "delete":
        return generateDeleteQuery(entityConfig, op.id, userId);
      default:
        throw new Error(`Unknown operation type: ${op.type}`);
    }
  });
}
function generateCountQuery(entityConfig, where = []) {
  const tableName = entityConfig.slug;
  const whereConditions = [];
  const params = [];
  let paramIndex = 1;
  if (true) {
    whereConditions.push(`${tableName}.deleted_at IS NULL`);
  }
  where.forEach((condition, index) => {
    const connector = index > 0 && condition.connector ? condition.connector : "AND";
    const placeholder = `$${paramIndex++}`;
    const conditionSql = buildWhereCondition(condition, placeholder, tableName);
    if (whereConditions.length > 0) {
      whereConditions.push(`${connector} ${conditionSql}`);
    } else {
      whereConditions.push(conditionSql);
    }
    params.push(formatParamValue(condition.value, condition.operator));
  });
  const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" ")}` : "";
  const sql = `SELECT COUNT(*) as total FROM ${tableName} ${whereClause}`.trim();
  return { sql, params };
}
function generateSelectFields(entityConfig) {
  const tableName = entityConfig.slug;
  const fields = ["id"];
  entityConfig.fields.filter((field) => true).forEach((field) => {
    if (!fields.includes(field.name)) {
      fields.push(field.name);
    }
  });
  if (true) {
    fields.push("created_at", "updated_at");
    if (true) {
      fields.push("deleted_at");
    }
  }
  return fields.map((field) => `${tableName}.${field}`);
}
function getInsertableFields(entityConfig) {
  return entityConfig.fields.filter(
    (field) => field.name !== "id" && field.name !== "createdAt" && field.name !== "updatedAt"
  );
}
function getUpdatableFields(entityConfig) {
  return entityConfig.fields.filter(
    (field) => field.name !== "id" && field.name !== "createdAt" && field.name !== "updatedAt"
  );
}
function buildWhereCondition(condition, placeholder, tableName) {
  const fieldName = `${tableName}.${condition.field}`;
  switch (condition.operator) {
    case "eq":
      return `${fieldName} = ${placeholder}`;
    case "neq":
      return `${fieldName} != ${placeholder}`;
    case "gt":
      return `${fieldName} > ${placeholder}`;
    case "gte":
      return `${fieldName} >= ${placeholder}`;
    case "lt":
      return `${fieldName} < ${placeholder}`;
    case "lte":
      return `${fieldName} <= ${placeholder}`;
    case "like":
      return `${fieldName} LIKE ${placeholder}`;
    case "ilike":
      return `${fieldName} ILIKE ${placeholder}`;
    case "in":
      return `${fieldName} = ANY(${placeholder})`;
    case "notin":
      return `${fieldName} != ALL(${placeholder})`;
    case "is":
      return `${fieldName} IS ${placeholder}`;
    case "isnot":
      return `${fieldName} IS NOT ${placeholder}`;
    default:
      return `${fieldName} = ${placeholder}`;
  }
}
function formatParamValue(value, operator) {
  if (operator === "like" || operator === "ilike") {
    return `%${value}%`;
  }
  if (operator === "in" || operator === "notin") {
    return Array.isArray(value) ? value : [value];
  }
  return value;
}
function formatFieldValue(value, field) {
  if (value === null || value === void 0) {
    return null;
  }
  switch (field.type) {
    case "json":
      return typeof value === "string" ? value : JSON.stringify(value);
    case "boolean":
      return Boolean(value);
    case "number":
      return Number(value);
    case "date":
    case "datetime":
      return value instanceof Date ? value.toISOString() : value;
    default:
      return value;
  }
}
export {
  generateBulkQueries,
  generateChildDeleteQuery,
  generateChildEntityQueries,
  generateChildInsertQuery,
  generateChildUpdateQuery,
  generateCountQuery,
  generateDeleteQuery,
  generateInsertQuery,
  generateSelectQuery,
  generateUpdateQuery
};
