const Migration = require('../models/migration');

/**
 * Kiểm tra xem migration đã chạy chưa
 * @param {string} migrationName - Tên của migration
 * @returns {Promise<boolean>} - true nếu đã chạy, false nếu chưa
 */
async function hasRun(migrationName) {
  try {
    const migration = await Migration.findOne({ name: migrationName });
    return !!migration;
  } catch (error) {
    console.error(`Error checking migration ${migrationName}:`, error);
    throw error;
  }
}

/**
 * Đánh dấu migration đã chạy
 * @param {string} migrationName - Tên của migration
 * @param {number} batch - Số batch (mặc định là batch hiện tại + 1)
 * @returns {Promise<Object>} - Migration document đã tạo
 */
async function markAsRun(migrationName, batch = null) {
  try {
    // Nếu không có batch, lấy batch cao nhất + 1
    if (batch === null) {
      const lastBatch = await Migration.findOne().sort({ batch: -1 });
      batch = lastBatch ? lastBatch.batch + 1 : 1;
    }

    const migration = await Migration.create({
      name: migrationName,
      batch: batch,
      ranAt: new Date()
    });

    return migration;
  } catch (error) {
    // Nếu migration đã tồn tại (unique constraint), trả về migration hiện có
    if (error.code === 11000) {
      return await Migration.findOne({ name: migrationName });
    }
    console.error(`Error marking migration ${migrationName} as run:`, error);
    throw error;
  }
}

/**
 * Lấy danh sách tất cả các migration đã chạy
 * @returns {Promise<Array>} - Danh sách các migration đã chạy
 */
async function getRanMigrations() {
  try {
    const migrations = await Migration.find().sort({ batch: 1, ranAt: 1 });
    return migrations;
  } catch (error) {
    console.error('Error getting ran migrations:', error);
    throw error;
  }
}

/**
 * Lấy danh sách các migration đã chạy theo batch
 * @param {number} batch - Số batch
 * @returns {Promise<Array>} - Danh sách các migration trong batch
 */
async function getMigrationsByBatch(batch) {
  try {
    const migrations = await Migration.find({ batch }).sort({ ranAt: 1 });
    return migrations;
  } catch (error) {
    console.error(`Error getting migrations for batch ${batch}:`, error);
    throw error;
  }
}

/**
 * Xóa migration khỏi bảng tracking (rollback)
 * @param {string} migrationName - Tên của migration
 * @returns {Promise<boolean>} - true nếu xóa thành công
 */
async function rollback(migrationName) {
  try {
    const result = await Migration.deleteOne({ name: migrationName });
    return result.deletedCount > 0;
  } catch (error) {
    console.error(`Error rolling back migration ${migrationName}:`, error);
    throw error;
  }
}

/**
 * Xóa tất cả migration trong một batch (rollback batch)
 * @param {number} batch - Số batch cần rollback
 * @returns {Promise<number>} - Số lượng migration đã xóa
 */
async function rollbackBatch(batch) {
  try {
    const result = await Migration.deleteMany({ batch });
    return result.deletedCount;
  } catch (error) {
    console.error(`Error rolling back batch ${batch}:`, error);
    throw error;
  }
}

/**
 * Lấy batch số cao nhất
 * @returns {Promise<number>} - Batch số cao nhất
 */
async function getLastBatch() {
  try {
    const lastBatch = await Migration.findOne().sort({ batch: -1 });
    return lastBatch ? lastBatch.batch : 0;
  } catch (error) {
    console.error('Error getting last batch:', error);
    throw error;
  }
}

/**
 * Chạy migration với tracking tự động
 * @param {string} migrationName - Tên của migration
 * @param {Function} migrationFunction - Hàm migration cần chạy
 * @returns {Promise<Object>} - Kết quả migration
 */
async function runMigration(migrationName, migrationFunction) {
  try {
    // Kiểm tra xem đã chạy chưa
    if (await hasRun(migrationName)) {
      console.log(`⏭️  Migration ${migrationName} đã chạy, bỏ qua...`);
      return { skipped: true, name: migrationName };
    }

    console.log(`🔄 Đang chạy migration: ${migrationName}...`);
    
    // Chạy migration function
    await migrationFunction();
    
    // Đánh dấu đã chạy
    const migration = await markAsRun(migrationName);
    
    console.log(`✅ Migration ${migrationName} đã chạy thành công! (Batch: ${migration.batch})`);
    
    return { 
      success: true, 
      name: migrationName, 
      batch: migration.batch,
      ranAt: migration.ranAt 
    };
  } catch (error) {
    console.error(`❌ Lỗi khi chạy migration ${migrationName}:`, error);
    throw error;
  }
}

module.exports = {
  hasRun,
  markAsRun,
  getRanMigrations,
  getMigrationsByBatch,
  rollback,
  rollbackBatch,
  getLastBatch,
  runMigration
};

