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

/**
 * Module gérant l'initialisation et la maintenance de la structure de la base de données
 */
class DatabaseManager {
  /**
   * Crée les tables de la base de données si elles n'existent pas déjà
   */
  static async createDatabase() {
    const queries = [
      `CREATE TABLE IF NOT EXISTS projects (
        id SERIAL PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        description TEXT,
        start_date DATE,
        status INTEGER NOT NULL CHECK (status = ANY (ARRAY [0, 1, 2, 3]))
      );`,
      `ALTER TABLE projects OWNER TO timelapse;`,
      `CREATE TABLE IF NOT EXISTS measurements (
        id SERIAL PRIMARY KEY,
        project_id INTEGER REFERENCES projects ON DELETE CASCADE,
        timestamp TIMESTAMP NOT NULL,
        path VARCHAR(255),
        temperature DOUBLE PRECISION,
        humidity DOUBLE PRECISION,
        order_id INTEGER NOT NULL,
        CONSTRAINT unique_project_photo_order UNIQUE (project_id, order_id)
      );`,
      `ALTER TABLE measurements OWNER TO timelapse;`,
      `CREATE TABLE IF NOT EXISTS videos (
        id SERIAL PRIMARY KEY,
        project_id INTEGER REFERENCES projects ON DELETE CASCADE,
        measurement_ids TEXT NOT NULL,
        video_file VARCHAR(255),
        resolution VARCHAR(255),
        duration INTEGER,
        status INTEGER NOT NULL CHECK (status = ANY (ARRAY [0, 1, 2, 3])),
        name VARCHAR(255),
        progress DOUBLE PRECISION,
        started_at TIMESTAMP,
        updated_at TIMESTAMP,
        eta DOUBLE PRECISION
      );`,
      `ALTER TABLE videos OWNER TO timelapse;`,
      `CREATE TABLE IF NOT EXISTS camera (
        id SERIAL PRIMARY KEY,
        interval INTEGER NOT NULL,
        maintenance INTEGER NOT NULL,
        active INTEGER DEFAULT 0 NOT NULL
      );`,
      `ALTER TABLE camera OWNER TO timelapse;`
    ];

    try {
      for (const query of queries) {
        await db.query(query);
      }
      console.log('[DB] Tables créées ou vérifiées avec succès.');
    } catch (err) {
      console.error('[DB] Erreur lors de la création des tables:', err);
      throw err;
    }
  }

  /**
   * Vérifie l'existence des tables requises dans la base de données
   */
  static async checkDatabaseExistence() {
    const query = `
      SELECT table_name 
      FROM information_schema.tables 
      WHERE table_schema = 'public' 
      AND table_name IN ('projects', 'measurements', 'videos', 'camera');
    `;

    try {
      const result = await db.query(query);
      const existingTables = result.rows.map(row => row.table_name);

      const requiredTables = ['projects', 'measurements', 'videos', 'camera'];
      const missingTables = requiredTables.filter(table => !existingTables.includes(table));

      if (missingTables.length > 0) {
        console.error('[DB] Tables manquantes ou incorrectement construites:', missingTables);
        throw new Error(`Les tables suivantes sont manquantes ou incorrectement construites: ${missingTables.join(', ')}`);
      } else {
        console.log('[DB] Toutes les tables requises existent et sont correctement construites.');
      }
    } catch (err) {
      console.error('[DB] Erreur lors de la vérification des tables:', err);
      throw err;
    }
  }

  /**
   * Supprime toutes les tables de la base de données
   */
  static async deleteDatabase() {
    const queries = [
      `DROP TABLE IF EXISTS videos;`,
      `DROP TABLE IF EXISTS measurements;`,
      `DROP TABLE IF EXISTS projects;`,
      `DROP TABLE IF EXISTS camera;`
    ];

    try {
      for (const query of queries) {
        await db.query(query);
      }
      console.log('[DB] Tables supprimées avec succès.');
    } catch (err) {
      console.error('[DB] Erreur lors de la suppression des tables:', err);
      throw err;
    }
  }

  /**
   * Initialise la base de données en vérifiant et en créant les tables si nécessaire
   */
  static async initialize() {
    try {
      await this.checkDatabaseExistence();
      console.log('[DB] Structure de base de données validée');
    } catch (err) {
      console.error('[DB] Vérification de la base de données échouée:', err);
      try {
        await this.deleteDatabase();
        await this.createDatabase();
        console.log('[DB] Base de données initialisée avec succès.');
      } catch (err) {
        console.error('[DB] Erreur lors de l\'initialisation de la base de données:', err);
        throw err;
      }
    } finally {
      console.log('[DB] Processus d\'initialisation de la base de données terminé.');
    }
  }
}

module.exports = DatabaseManager;