/**
 * Inventory Item Model
 * UID-based inventory tracking (Layer 2 of dual inventory model)
 * Each physical unit has a unique UID (barcode/QR code)
 */

module.exports = (sequelize, DataTypes) => {
  // Define InventoryItem model
  const InventoryItem = sequelize.define('InventoryItem', {
    // Primary key
    id: {
      type: DataTypes.BIGINT, // Use BIGINT for large scale
      primaryKey: true, // Set as primary key
      autoIncrement: true, // Auto-increment ID
    },
    // Unique Identifier (UID) - barcode/QR code
    uid: {
      type: DataTypes.STRING(100), // UID with max length
      allowNull: false, // UID is required
      unique: true, // UID must be unique
      validate: {
        notEmpty: true, // UID cannot be empty string
        len: [1, 100], // UID length validation
      },
    },
    // Foreign key to Product
    product_id: {
      type: DataTypes.BIGINT, // Match Product ID type
      allowNull: false, // Product ID is required
      references: {
        model: 'products', // Reference to products table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on product update
      onDelete: 'CASCADE', // Cascade delete when product is deleted
    },
    // Current status of the inventory item
    status: {
      type: DataTypes.ENUM(
        'IN_STOCK',    // Item is in stock and available
        'RESERVED',    // Item is reserved (pending sale)
        'SOLD',        // Item has been sold
        'RETURNED',    // Item has been returned
        'DAMAGED',     // Item is damaged
        'SCRAPPED'     // Item has been scrapped
      ),
      defaultValue: 'IN_STOCK', // Default status is IN_STOCK
      allowNull: false, // Status is required
      validate: {
        isIn: [['IN_STOCK', 'RESERVED', 'SOLD', 'RETURNED', 'DAMAGED', 'SCRAPPED']], // Validate enum values
      },
    },
    // Source of the inventory item (how it entered the system)
    source: {
      type: DataTypes.ENUM(
        'GRN',        // Received from Goods Receipt Note
        'PRODUCTION', // Produced in-house
        'RETURN'      // Returned from customer
      ),
      allowNull: false, // Source is required
      validate: {
        isIn: [['GRN', 'PRODUCTION', 'RETURN']], // Validate enum values
      },
    },
    // Reference ID to the source document (GRN ID or Production Order ID)
    source_reference_id: {
      type: DataTypes.BIGINT, // Reference ID
      allowNull: true, // Optional (for RETURN items or legacy data)
      comment: 'GRN ID or Production Order ID that created this item',
    },
    // Barcode stored separately (added enhancement for explicit barcode storage)
    barcode: {
      type: DataTypes.STRING(100), // Barcode with max length
      allowNull: true, // Barcode is optional (can use UID instead)
      validate: {
        len: [0, 100], // Maximum length validation
      },
    },
  }, {
    // Model options
    tableName: 'inventory_items', // Explicit table name
    underscored: true, // Use snake_case for database columns
    timestamps: true, // Enable createdAt and updatedAt timestamps
    createdAt: 'created_at', // Map createdAt to created_at column
    updatedAt: 'updated_at', // Map updatedAt to updated_at column
    indexes: [
      // Unique index on UID (already enforced by unique constraint)
      {
        unique: true, // Unique index
        fields: ['uid'], // Index on UID field
      },
      // Index on product_id for faster lookups
      {
        fields: ['product_id'], // Index on product_id field
      },
      // Index on status for filtering by status
      {
        fields: ['status'], // Index on status field
      },
      // Index on barcode for barcode lookups
      {
        fields: ['barcode'], // Index on barcode field
      },
      // Composite index on source and source_reference_id for reprint queries
      {
        fields: ['source', 'source_reference_id'], // Composite index
      },
    ],
  });

  // Define model associations
  InventoryItem.associate = (models) => {
    // InventoryItem belongs to Product (many-to-one relationship)
    InventoryItem.belongsTo(models.Product, {
      foreignKey: 'product_id', // Foreign key in InventoryItem table
      as: 'product', // Alias for association
    });
    
    // InventoryItem has many InventoryMovements (one-to-many relationship)
    InventoryItem.hasMany(models.InventoryMovement, {
      foreignKey: 'inventory_item_id', // Foreign key in InventoryMovements table
      as: 'inventoryMovements', // Alias for association
    });
    
    // InventoryItem has many SaleItems (one-to-many relationship)
    InventoryItem.hasMany(models.SaleItem, {
      foreignKey: 'inventory_item_id', // Foreign key in SaleItems table
      as: 'saleItems', // Alias for association
    });
    
    // InventoryItem has many ReturnItems (one-to-many relationship)
    InventoryItem.hasMany(models.ReturnItem, {
      foreignKey: 'inventory_item_id', // Foreign key in ReturnItems table
      as: 'returnItems', // Alias for association
    });
  };

  // Return InventoryItem model
  return InventoryItem;
};

