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

/**
 * Modèle pour la gestion des vidéos
 */
class Video {
  /**
   * Récupère toutes les vidéos
   * @returns {Promise<Array>} Liste de toutes les vidéos
   */
  static getAllVideos = wrapDatabaseOperation(async () => {
    const query = `SELECT * FROM videos;`;
    return (await db.query(query)).rows;
  });

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

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

  /**
   * Crée une nouvelle vidéo
   * @param {number} projectId - ID du projet
   * @param {string} measurementIds - IDs des mesures (format JSON)
   * @param {string} name - Nom de la vidéo
   * @param {string} resolution - Résolution de la vidéo
   * @param {number} duration - Durée de la vidéo en secondes
   * @param {number} status - Statut de la vidéo (défaut: 0 = en attente)
   * @returns {Promise<Object>} Vidéo créée
   */
  static createVideo = wrapDatabaseOperation(async (
    projectId, measurementIds, name, resolution, duration, status = config.videoStatus.rendering
  ) => {
    const query = `
      INSERT INTO videos (project_id, measurement_ids, name, resolution, duration, status) 
      VALUES ($1, $2, $3, $4, $5, $6) 
      RETURNING *;
    `;
    const result = await db.query(
      query, [projectId, measurementIds, name, resolution, duration, status]
    );
    return result.rows[0];
  });

  /**
   * Met à jour une vidéo existante
   * @param {number} id - ID de la vidéo
   * @param {Object} updates - Champs à mettre à jour
   * @returns {Promise<Object|null>} Vidéo mise à jour ou null si non trouvée
   */
  static updateVideo = 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 videos SET ${fields} WHERE id = $1 RETURNING *;`;
    const result = await db.query(query, values);
    return result.rows[0] || null;
  });

  /**
   * Met à jour le chemin du fichier vidéo
   * @param {number} id - ID de la vidéo
   * @param {string} videoFile - Chemin du fichier vidéo
   * @returns {Promise<Object|null>} Vidéo mise à jour ou null si non trouvée
   */
  static updateVideoFilePath = wrapDatabaseOperation(async (id, videoFile) => {
    const query = `UPDATE videos SET video_file = $1 WHERE id = $2 RETURNING *;`;
    const result = await db.query(query, [videoFile, id]);
    return result.rows[0] || null;
  });

  /**
   * Met à jour le statut d'une vidéo
   * @param {number} id - ID de la vidéo
   * @param {number} status - Nouveau statut de la vidéo
   * @returns {Promise<Object|null>} Vidéo mise à jour ou null si non trouvée
   */
  static async updateVideoStatus(id, status) {
    const query = `UPDATE videos SET status = $1 WHERE id = $2 RETURNING *;`;
    const result = await db.query(query, [status, id]);
    return result.rows[0] || null;
  }

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

  /**
   * Récupère toutes les vidéos non terminées (statut 0, 2 ou 3)
   * @returns {Promise<Array>} Liste des vidéos non terminées
   */
  static getUnfinishedVideos = wrapDatabaseOperation(async () => {
    const query = `
      SELECT * FROM videos 
      WHERE status IN (
        ${config.videoStatus.rendering}, 
        ${config.videoStatus.error}, 
        0
      );
    `;
    return (await db.query(query)).rows;
  });

  /**
   * Met à jour la progression d'une vidéo en cours de rendu
   * @param {number} id - ID de la vidéo
   * @param {number} progress - Pourcentage de progression
   * @param {number} eta - Temps estimé restant en secondes
   * @returns {Promise<Object|null>} Vidéo mise à jour ou null si non trouvée
   */
  static updateVideoProgress = wrapDatabaseOperation(async (id, progress, eta) => {
    const query = `
      UPDATE videos 
      SET progress = $1, eta = $2, updated_at = NOW() 
      WHERE id = $3 
      RETURNING *;
    `;
    const result = await db.query(query, [progress, eta, id]);
    return result.rows[0] || null;
  });
}

module.exports = Video;