const BaseModel = require('./BaseModel');
const fs = require('fs');
const path = require('path');

class Migration extends BaseModel {
  constructor() {
    super('migrations');
  }

  async getRanMigrations() {
    const [rows] = await this.db.query('SELECT migration FROM migrations ORDER BY id ASC');
    return rows.map(row => row.migration);
  }

  async getLastBatchNumber() {
    const [rows] = await this.db.query('SELECT MAX(batch) as last_batch FROM migrations');
    return rows[0].last_batch || 0;
  }

  async log(migrationName, batch) {
    await this.db.query(
      'INSERT INTO migrations (migration, batch) VALUES (?, ?)',
      [migrationName, batch]
    );
  }

  async runMigrations() {
    const migrationsPath = path.join(__dirname, '../../database/migrations');
    
    // Get all migration files
    const migrationFiles = fs.readdirSync(migrationsPath)
      .filter(file => file.endsWith('.js') && file !== 'index.js')
      .sort();
    
    // Get already ran migrations
    const ranMigrations = await this.getRanMigrations();
    const lastBatch = await this.getLastBatchNumber();
    const currentBatch = lastBatch + 1;
    
    // Run new migrations
    for (const file of migrationFiles) {
      if (!ranMigrations.includes(file)) {
        try {
          const migration = require(path.join(migrationsPath, file));
          
          // Run migration
          if (typeof migration.up === 'function') {
            await migration.up(this.db);
          }
          
          // Log migration
          await this.log(file, currentBatch);
          console.log(`Migrated: ${file}`);
          
        } catch (error) {
          console.error(`Error running migration ${file}:`, error);
          throw error; // Stop execution on error
        }
      }
    }
    
    return true;
  }

  async rollbackMigrations(steps = 1) {
    // Get the last batch of migrations
    const [lastBatch] = await this.db.query(
      'SELECT DISTINCT batch FROM migrations ORDER BY batch DESC LIMIT ?',
      [steps]
    );
    
    if (lastBatch.length === 0) {
      console.log('Nothing to rollback');
      return true;
    }
    
    const batchNumbers = lastBatch.map(b => b.batch);
    
    // Get migrations to rollback
    const [migrations] = await this.db.query(
      'SELECT * FROM migrations WHERE batch IN (?) ORDER BY batch DESC, id DESC',
      [batchNumbers]
    );
    
    // Rollback migrations
    const migrationsPath = path.join(__dirname, '../../database/migrations');
    
    for (const migration of migrations) {
      try {
        const migrationFile = path.join(migrationsPath, migration.migration);
        
        if (fs.existsSync(migrationFile)) {
          const migrationModule = require(migrationFile);
          
          // Run down migration
          if (typeof migrationModule.down === 'function') {
            await migrationModule.down(this.db);
          }
          
          // Remove migration log
          await this.db.query('DELETE FROM migrations WHERE id = ?', [migration.id]);
          console.log(`Rolled back: ${migration.migration}`);
        } else {
          console.warn(`Migration file not found: ${migration.migration}`);
        }
      } catch (error) {
        console.error(`Error rolling back migration ${migration.migration}:`, error);
        throw error; // Stop execution on error
      }
    }
    
    return true;
  }
}

module.exports = new Migration();
