/**
 * Inventory Sync Fix Script
 * Fixes discrepancies between Inventory.quantity and InventoryItem counts
 * Ensures ACID compliance by recalculating quantity from InventoryItems
 */

require('dotenv').config({ path: require('path').join(__dirname, '../../.env') });
const { sequelize, Inventory, InventoryItem } = require('../models');
const logger = require('../utils/logger');

const Op = require('sequelize').Op;

/**
 * Fix inventory sync for a specific product/variant
 */
async function fixInventorySync(productId, variantId = null, dryRun = true) {
  const transaction = await sequelize.transaction();
  
  try {
    // Get inventory record
    const inventory = await Inventory.findOne({
      where: {
        product_id: productId,
        variant_id: variantId || null,
      },
      transaction,
    });

    if (!inventory) {
      logger.warn(`No inventory record found for product_id=${productId}, variant_id=${variantId}`);
      return { fixed: false, reason: 'No inventory record' };
    }

    // Count actual IN_STOCK items
    const actualCount = await InventoryItem.count({
      where: {
        product_id: productId,
        variant_id: variantId || null,
        status: 'IN_STOCK',
      },
      transaction,
    });

    const currentQuantity = parseFloat(inventory.quantity || 0);
    const discrepancy = actualCount - currentQuantity;

    if (discrepancy === 0) {
      logger.info(`✅ Product ${productId}, variant ${variantId}: No discrepancy (${actualCount})`);
      await transaction.rollback();
      return { fixed: false, discrepancy: 0, current: currentQuantity, actual: actualCount };
    }

    logger.warn(
      `⚠️  Product ${productId}, variant ${variantId}: DISCREPANCY DETECTED! ` +
      `Current quantity: ${currentQuantity}, Actual IN_STOCK items: ${actualCount}, Difference: ${discrepancy}`
    );

    if (!dryRun) {
      // Update inventory quantity to match actual count
      inventory.quantity = actualCount;
      await inventory.save({ transaction });
      await transaction.commit();
      
      logger.info(
        `✅ FIXED: Product ${productId}, variant ${variantId}: Updated quantity from ${currentQuantity} to ${actualCount}`
      );
    } else {
      await transaction.rollback();
      logger.info(`[DRY RUN] Would update quantity from ${currentQuantity} to ${actualCount}`);
    }

    return {
      fixed: !dryRun && discrepancy !== 0,
      discrepancy,
      current: currentQuantity,
      actual: actualCount,
      productId,
      variantId,
    };
  } catch (error) {
    await transaction.rollback();
    logger.error(`Error fixing inventory sync for product ${productId}, variant ${variantId}:`, error);
    throw error;
  }
}

/**
 * Fix all inventory discrepancies
 */
async function fixAllInventorySync(dryRun = true) {
  logger.info(`Starting inventory sync fix (dryRun=${dryRun})...`);
  
  // Get all inventory records
  const inventories = await Inventory.findAll({
    attributes: ['product_id', 'variant_id'],
    group: ['product_id', 'variant_id'],
  });

  const results = [];
  
  for (const inv of inventories) {
    try {
      const result = await fixInventorySync(inv.product_id, inv.variant_id, dryRun);
      results.push(result);
    } catch (error) {
      logger.error(`Error processing inventory ${inv.product_id}/${inv.variant_id}:`, error);
      results.push({
        productId: inv.product_id,
        variantId: inv.variant_id,
        error: error.message,
      });
    }
  }

  const fixedCount = results.filter(r => r.fixed).length;
  const discrepancyCount = results.filter(r => r.discrepancy !== 0 && r.discrepancy !== undefined).length;
  
  logger.info(`\n=== Inventory Sync Fix Summary ===`);
  logger.info(`Total inventories checked: ${results.length}`);
  logger.info(`With discrepancies: ${discrepancyCount}`);
  logger.info(`Fixed: ${fixedCount}`);
  
  if (dryRun) {
    logger.info(`\n⚠️  This was a DRY RUN. No changes were made.`);
    logger.info(`Run with dryRun=false to apply fixes.`);
  }

  return results;
}

/**
 * Main execution
 */
async function main() {
  const args = process.argv.slice(2);
  const dryRun = !args.includes('--apply');
  const productId = args.find(arg => arg.startsWith('--product='))?.split('=')[1];
  const variantId = args.find(arg => arg.startsWith('--variant='))?.split('=')[1];

  try {
    await sequelize.authenticate();
    logger.info('Database connected successfully');

    if (productId) {
      // Fix specific product/variant
      const result = await fixInventorySync(
        parseInt(productId),
        variantId ? parseInt(variantId) : null,
        dryRun
      );
      console.log(JSON.stringify(result, null, 2));
    } else {
      // Fix all
      const results = await fixAllInventorySync(dryRun);
      console.log('\nResults:');
      console.log(JSON.stringify(results, null, 2));
    }

    process.exit(0);
  } catch (error) {
    logger.error('Fatal error:', error);
    process.exit(1);
  }
}

// Run if executed directly
if (require.main === module) {
  main();
}

module.exports = {
  fixInventorySync,
  fixAllInventorySync,
};

