/**
 * Inventory Reconciliation Service
 * Identifies and fixes discrepancies between quantity-based and UID-based inventory
 */

const { Inventory, InventoryItem, Product } = require('../../../models');
const { Op } = require('sequelize');
const logger = require('../../../utils/logger');

/**
 * Check for inventory discrepancies
 * @param {number|null} productId - Optional product ID to check specific product
 * @returns {Promise<Array>} Array of discrepancy reports
 */
const checkDiscrepancies = async (productId = null) => {
  const discrepancies = [];

  // Get all inventory records (or specific product)
  const whereClause = {};
  if (productId) {
    whereClause.product_id = productId;
  }

  const inventoryRecords = await Inventory.findAll({
    where: whereClause,
    include: [
      {
        model: Product,
        as: 'product',
        attributes: ['id', 'name', 'sku', 'track_inventory'],
      },
    ],
  });

  for (const inventory of inventoryRecords) {
    // Skip if product doesn't track inventory
    if (!inventory.product || !inventory.product.track_inventory) {
      continue;
    }

    // Count UID-based inventory items in stock
    const uidBasedCount = await InventoryItem.count({
      where: {
        product_id: inventory.product_id,
        variant_id: inventory.variant_id,
        status: 'IN_STOCK',
      },
    });

    const quantityBased = parseFloat(inventory.quantity || 0);
    const difference = Math.abs(quantityBased - uidBasedCount);

    // If there's a discrepancy
    if (difference > 0) {
      discrepancies.push({
        inventory_id: inventory.id,
        product_id: inventory.product_id,
        product_name: inventory.product.name,
        product_sku: inventory.product.sku,
        variant_id: inventory.variant_id,
        quantity_based: quantityBased,
        uid_based: uidBasedCount,
        difference: difference,
        discrepancy_type: quantityBased > uidBasedCount ? 'QUANTITY_HIGHER' : 'UID_HIGHER',
      });
    }
  }

  return discrepancies;
};

/**
 * Reconcile inventory discrepancies
 * Option 1: Sync quantity to match UID count (recommended if UID records are accurate)
 * Option 2: Sync UID records to match quantity (use if quantity is accurate)
 * @param {Array} discrepancies - Array of discrepancies to fix
 * @param {string} syncMethod - 'QUANTITY_TO_UID' or 'UID_TO_QUANTITY'
 * @returns {Promise<Object>} Reconciliation results
 */
const reconcileDiscrepancies = async (discrepancies, syncMethod = 'QUANTITY_TO_UID') => {
  const results = {
    fixed: [],
    errors: [],
    skipped: [],
  };

  for (const discrepancy of discrepancies) {
    try {
      const inventory = await Inventory.findByPk(discrepancy.inventory_id);
      if (!inventory) {
        results.errors.push({
          ...discrepancy,
          error: 'Inventory record not found',
        });
        continue;
      }

      if (syncMethod === 'QUANTITY_TO_UID') {
        // Update Inventory quantity to match UID count
        // This assumes UID records are the source of truth
        inventory.quantity = discrepancy.uid_based;
        await inventory.save();

        logger.info(`Reconciled inventory ${inventory.id}: Updated quantity from ${discrepancy.quantity_based} to ${discrepancy.uid_based} (matched UID count)`);

        results.fixed.push({
          ...discrepancy,
          action: 'Updated quantity to match UID count',
          new_quantity: discrepancy.uid_based,
        });
      } else if (syncMethod === 'UID_TO_QUANTITY') {
        // This method would require creating/deleting InventoryItem records
        // which is more complex and risky, so we'll skip it for now
        results.skipped.push({
          ...discrepancy,
          reason: 'UID_TO_QUANTITY sync not yet implemented (requires creating/deleting InventoryItem records)',
        });
      }
    } catch (error) {
      logger.error(`Error reconciling inventory ${discrepancy.inventory_id}:`, error);
      results.errors.push({
        ...discrepancy,
        error: error.message,
      });
    }
  }

  return results;
};

/**
 * Get reconciliation report
 * @param {number|null} productId - Optional product ID
 * @returns {Promise<Object>} Detailed reconciliation report
 */
const getReconciliationReport = async (productId = null) => {
  const discrepancies = await checkDiscrepancies(productId);

  const report = {
    total_discrepancies: discrepancies.length,
    discrepancies: discrepancies,
    summary: {
      quantity_higher: discrepancies.filter(d => d.discrepancy_type === 'QUANTITY_HIGHER').length,
      uid_higher: discrepancies.filter(d => d.discrepancy_type === 'UID_HIGHER').length,
      total_difference: discrepancies.reduce((sum, d) => sum + d.difference, 0),
    },
    timestamp: new Date(),
  };

  return report;
};

/**
 * Auto-reconcile all discrepancies using UID count as source of truth
 * @param {number|null} productId - Optional product ID to reconcile specific product
 * @returns {Promise<Object>} Reconciliation results
 */
const autoReconcile = async (productId = null) => {
  logger.info(`Starting automatic inventory reconciliation${productId ? ` for product ${productId}` : ''}`);

  const discrepancies = await checkDiscrepancies(productId);

  if (discrepancies.length === 0) {
    logger.info('No inventory discrepancies found');
    return {
      fixed: [],
      errors: [],
      skipped: [],
      message: 'No discrepancies found',
    };
  }

  logger.info(`Found ${discrepancies.length} inventory discrepancies, reconciling...`);

  const results = await reconcileDiscrepancies(discrepancies, 'QUANTITY_TO_UID');

  logger.info(`Reconciliation complete: ${results.fixed.length} fixed, ${results.errors.length} errors, ${results.skipped.length} skipped`);

  return results;
};

module.exports = {
  checkDiscrepancies,
  reconcileDiscrepancies,
  getReconciliationReport,
  autoReconcile,
};

