// src/models/Measurement.js
const db = require('../database/connection');
const { wrapDatabaseOperation } = require('../utils/errorHandler');

/**
 * Modèle pour la gestion des mesures (photos avec données)
 */
class Measurement {
  /**
   * Récupère toutes les mesures
   * @returns {Promise<Array>} Liste de toutes les mesures
   */
  static getAllMeasurements = wrapDatabaseOperation(async () => {
    const query = `SELECT * FROM measurements;`;
    return (await db.query(query)).rows;
  });

  /**
   * Récupère une mesure par son ID
   * @param {number} id - ID de la mesure
   * @returns {Promise<Object|null>} Détails de la mesure ou null si non trouvée
   */
  static getMeasurementById = wrapDatabaseOperation(async (id) => {
    const query = `SELECT * FROM measurements WHERE id = $1;`;
    const result = await db.query(query, [id]);
    return result.rows[0] || null;
  });

  /**
   * Récupère une mesure par son projet ID et son ordre ID
   * @param {number} projectId - ID du projet
   * @param {number} orderId - ID d'ordre de la mesure
   * @returns {Promise<Object|null>} Détails de la mesure ou null si non trouvée
   */
  static getMeasurementByProjectAndOrderId = wrapDatabaseOperation(async (projectId, orderId) => {
    const query = `SELECT * FROM measurements WHERE project_id = $1 AND order_id = $2;`;
    const result = await db.query(query, [projectId, orderId]);
    return result.rows[0] || null;
  });

  /**
   * Récupère toutes les mesures d'un projet
   * @param {number} projectId - ID du projet
   * @returns {Promise<Array>} Liste des mesures du projet
   */
  static getMeasurementsByProjectId = wrapDatabaseOperation(async (projectId) => {
    const query = `SELECT * FROM measurements WHERE project_id = $1 ORDER BY order_id;`;
    return (await db.query(query, [projectId])).rows;
  });

  /**
   * Crée une nouvelle mesure
   * @param {number} projectId - ID du projet
   * @param {string} timestamp - Horodatage de la mesure
   * @param {string} path - Chemin vers l'image
   * @param {number} temperature - Température mesurée
   * @param {number} humidity - Humidité mesurée
   * @param {number} orderId - Ordre séquentiel de la mesure
   * @returns {Promise<Object>} Mesure créée
   */
  static createMeasurement = wrapDatabaseOperation(async (
    projectId, timestamp, path, temperature, humidity, orderId
  ) => {
    const query = `
      INSERT INTO measurements (project_id, timestamp, path, temperature, humidity, order_id) 
      VALUES ($1, $2, $3, $4, $5, $6) 
      RETURNING *;
    `;
    const result = await db.query(
      query, [projectId, timestamp, path, temperature, humidity, orderId]
    );
    return result.rows[0];
  });

  /**
   * Met à jour une mesure existante
   * @param {number} id - ID de la mesure
   * @param {Object} updates - Champs à mettre à jour
   * @returns {Promise<Object|null>} Mesure mise à jour ou null si non trouvée
   */
  static updateMeasurement = wrapDatabaseOperation(async (id, updates) => {
    const fields = Object.keys(updates).map((key, index) => `${key} = $${index + 2}`).join(', ');
    const values = [id, ...Object.values(updates)];
    const query = `UPDATE measurements SET ${fields} WHERE id = $1 RETURNING *;`;
    const result = await db.query(query, values);
    return result.rows[0] || null;
  });

  /**
   * Met à jour une mesure par projet ID et ordre ID
   * @param {number} projectId - ID du projet
   * @param {number} orderId - ID d'ordre de la mesure
   * @param {Object} updates - Champs à mettre à jour
   * @returns {Promise<Object|null>} Mesure mise à jour ou null si non trouvée
   */
  static updateMeasurementByProjectAndOrderId = wrapDatabaseOperation(async (projectId, orderId, updates) => {
    const fields = Object.keys(updates).map((key, index) => `${key} = $${index + 3}`).join(', ');
    const values = [projectId, orderId, ...Object.values(updates)];
    const query = `UPDATE measurements SET ${fields} WHERE project_id = $1 AND order_id = $2 RETURNING *;`;
    const result = await db.query(query, values);
    return result.rows[0] || null;
  });

  /**
   * Supprime une mesure par son ID
   * @param {number} id - ID de la mesure
   * @returns {Promise<void>}
   */
  static deleteMeasurement = wrapDatabaseOperation(async (id) => {
    const query = `DELETE FROM measurements WHERE id = $1;`;
    await db.query(query, [id]);
  });

  /**
   * Obtient le prochain ordre ID disponible pour un projet
   * @param {number} projectId - ID du projet
   * @returns {Promise<number>} Prochain ordre ID
   */
  static getNextOrderId = wrapDatabaseOperation(async (projectId) => {
    const query = `SELECT COALESCE(MAX(order_id), 0) + 1 AS next_order_id FROM measurements WHERE project_id = $1;`;
    const result = await db.query(query, [projectId]);
    return result.rows[0].next_order_id;
  });
}

module.exports = Measurement;