const sequelize = require('./config/db'); // Assuming sequelize is configured in a separate file

// Example 1: Basic sync with no options
// This creates tables for all defined models if they don't exist, but won't modify existing tables
(async () => {
  try {
    await sequelize.sync();
    console.log('✅ Database synchronized successfully (no schema changes made).');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 2: Sync with { force: true }
// Dops all existing tables and recrreates them from the model definitions
// WARNING: This will delete all data in the database, use with caution
(async () => {
  try {
    await sequelize.sync({ force: true });
    console.log('✅ Database synchronized successfully (tables dropped and recreated).');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 3: Sync with { alter: true }
// Modifies existing tables to match model definitions (e.g., adds/removes columns)
// Preserves data where possible, but some changes may result in data loss
(async () => {
  try {
    await sequelize.sync({ alter: true });
    console.log('✅ Database synchronized successfully (tables altered to match models).');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 4: Sync with { alter: { drop: false } }
// Alters tables to match models but prevents dropping columns or tables
// Safer option for production to avoid accidental data loss
(async () => {
  try {
    await sequelize.sync({ alter: { drop: false } });
    console.log('✅ Database synchronized successfully (tables altered, no columns dropped).');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 5: Sync specific models only
// Synchronizes only the specified model(s) instead of all defined models
const User = require('./models/User'); // Example model
(async () => {
  try {
    await User.sync({ alter: true });
    console.log('✅ User model synchronized successfully.');
  } catch (error) {
    console.error('❌ Failed to sync User model:', error.message);
  }
})();

// Example 6: Conditional sync based on environment
// Uses different sync options depending on the environment (e.g., development vs production)
require('dotenv').config();
(async () => {
  try {
    const syncOptions = process.env.NODE_ENV === 'production'
      ? { alter: { drop: false } } // Safer for production
      : { force: true }; // More aggressive for development
    await sequelize.sync(syncOptions);
    console.log(`✅ Database synchronized successfully in ${process.env.NODE_ENV} mode.`);
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 7: Sync with logging
// Enables detailed logging to track the SQL queries executed during sync
(async () => {
  try {
    await sequelize.sync({
      alter: true,
      logging: (msg) => console.log('🔍 Sequelize:', msg) // Log SQL queries
    });
    console.log('✅ Database synchronized successfully with logging.');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 8: Sync with schema option
// Specifies a database schema to sync models to (useful for databases supporting schemas)
(async () => {
  try {
    await sequelize.sync({
      alter: true,
      schema: 'emtaf_bursary' // Example schema name
    });
    console.log('✅ Database synchronized successfully for schema: emtaf_bursary.');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 9: Sync with hooks
// Uses Sequelize hooks to perform actions before/after sync
const { Sequelize } = require('sequelize');
(async () => {
  try {
    sequelize.beforeSync(() => {
      console.log('📌 Starting database synchronization...');
    });
    sequelize.afterSync(() => {
      console.log('🎉 Database synchronization completed.');
    });
    await sequelize.sync({ alter: true });
    console.log('✅ Database synchronized successfully with hooks.');
  } catch (error) {
    console.error('❌ Failed to sync database:', error.message);
  }
})();

// Example 10: Sync with transaction
// Wraps the sync operation in a transaction for atomicity
(async () => {
  const t = await sequelize.transaction();
  try {
    await sequelize.sync({ alter: true, transaction: t });
    await t.commit();
    console.log('✅ Database synchronized successfully within transaction.');
  } catch (error) {
    await t.rollback();
    console.error('❌ Failed to sync database:', error.message);
  }
})();