/**
 * BOM Item Model
 * Defines raw materials and quantities needed per unit of finished good
 */

module.exports = (sequelize, DataTypes) => {
  // Define BOMItem model
  const BOMItem = sequelize.define('BOMItem', {
    // Primary key
    id: {
      type: DataTypes.BIGINT, // Use BIGINT for large scale
      primaryKey: true, // Set as primary key
      autoIncrement: true, // Auto-increment ID
    },
    // Foreign key to BOM
    bom_id: {
      type: DataTypes.BIGINT, // Match BOM ID type
      allowNull: false, // BOM ID is required
      references: {
        model: 'boms', // Reference to boms table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on BOM update
      onDelete: 'CASCADE', // Cascade delete when BOM is deleted
    },
    // Foreign key to Product (Raw Material)
    rm_product_id: {
      type: DataTypes.BIGINT, // Match Product ID type
      allowNull: false, // Raw material product ID is required
      references: {
        model: 'products', // Reference to products table
        key: 'id', // Reference to id column
      },
      onUpdate: 'CASCADE', // Cascade update on product update
    },
    // Item type (FABRIC, BUTTONS, ZIPPER, LINING, ELASTIC)
    item_type: {
      type: DataTypes.ENUM('FABRIC', 'BUTTONS', 'ZIPPER', 'LINING', 'ELASTIC'), // Item type enum
      allowNull: true, // Optional - can be inferred from product name or set explicitly
      comment: 'Type of raw material item (FABRIC, BUTTONS, ZIPPER, LINING, ELASTIC)',
    },
    // Quantity of raw material needed per unit of finished good (for quantity-based RM)
    quantity_per_unit: {
      type: DataTypes.DECIMAL(12, 3), // Decimal with 12 digits, 3 decimal places
      allowNull: true, // Nullable - only set for quantity-based items
      validate: {
        min: 0, // Quantity cannot be negative
      },
      comment: 'Quantity per unit (for quantity-based RM like buttons, zippers). NULL for dimension-based items.',
    },
    // Dimension requirement fields for RM products (for dimension-based RM)
    required_length: {
      type: DataTypes.DECIMAL(12, 3), // Required length per unit of FG product
      allowNull: true, // Nullable - only set for dimension-based items
      validate: {
        min: 0, // Length cannot be negative
      },
      comment: 'Required length per unit (for dimension-based RM like fabric). NULL for quantity-based items.',
    },
    required_width: {
      type: DataTypes.DECIMAL(12, 3), // Required width per unit of FG product
      allowNull: true, // Nullable - only set for dimension-based items
      validate: {
        min: 0, // Width cannot be negative
      },
      comment: 'Required width per unit (for dimension-based RM like fabric). NULL for quantity-based items.',
    },
    dimension_unit: {
      type: DataTypes.ENUM('inch', 'cm', 'm'), // Unit of measure for dimension requirements
      allowNull: true, // Nullable - only set for dimension-based items
      comment: 'Dimension unit (for dimension-based RM like fabric). NULL for quantity-based items.',
    },
    // Note: use_dimensions removed - derive from products.track_by_dimensions
  }, {
    // Model options
    tableName: 'bom_items', // Explicit table name
    underscored: true, // Use snake_case for database columns
    timestamps: false, // No timestamps for BOM items
    indexes: [
      // Index on bom_id for faster lookups
      {
        fields: ['bom_id'], // Index on bom_id field
      },
      // Index on rm_product_id for faster lookups
      {
        fields: ['rm_product_id'], // Index on rm_product_id field
      },
      // Note: use_dimensions index removed - derive from product instead
      // Index on dimension requirements for allocation queries
      {
        fields: ['required_length', 'required_width', 'dimension_unit'], // Composite index
      },
    ],
    // Add validation hooks
    hooks: {
      beforeValidate: async (bomItem, options) => {
        // Validate: either quantity-based OR dimension-based, not both, not neither
        const hasQuantity = bomItem.quantity_per_unit !== null && bomItem.quantity_per_unit !== undefined;
        const hasDimensions = bomItem.required_length !== null && 
                              bomItem.required_width !== null && 
                              bomItem.dimension_unit !== null;
        
        if (hasQuantity && hasDimensions) {
          throw new Error('BOM item cannot have both quantity_per_unit and dimension fields set');
        }
        
        if (!hasQuantity && !hasDimensions) {
          throw new Error('BOM item must have either quantity_per_unit (quantity-based) or dimension fields (dimension-based)');
        }
        
        // Validate dimension requirements if dimension-based
        if (hasDimensions) {
          if (parseFloat(bomItem.required_length) <= 0 || parseFloat(bomItem.required_width) <= 0) {
            throw new Error('Required dimensions must be positive');
          }
        }
        
        // Validate quantity if quantity-based
        if (hasQuantity) {
          if (parseFloat(bomItem.quantity_per_unit) <= 0) {
            throw new Error('Quantity per unit must be positive');
          }
        }
      },
    },
  });

  // Define model associations
  BOMItem.associate = (models) => {
    // BOMItem belongs to BOM (many-to-one relationship)
    BOMItem.belongsTo(models.BOM, {
      foreignKey: 'bom_id', // Foreign key in BOMItem table
      as: 'bom', // Alias for association
    });
    
    // BOMItem belongs to Product (many-to-one relationship) - as Raw Material
    BOMItem.belongsTo(models.Product, {
      foreignKey: 'rm_product_id', // Foreign key in BOMItem table
      as: 'rawMaterial', // Alias for association
    });
  };

  // Add instance methods for dimension-based operations
  BOMItem.prototype.getRequiredArea = function() {
    // Check if dimension-based (has dimension fields)
    if (!this.required_length || !this.required_width) {
      return null;
    }
    return parseFloat(this.required_length) * parseFloat(this.required_width);
  };

  BOMItem.prototype.calculateTotalAreaRequired = function(productionQuantity) {
    const areaPerUnit = this.getRequiredArea();
    if (areaPerUnit === null) {
      return null;
    }
    return areaPerUnit * productionQuantity;
  };

  BOMItem.prototype.isDimensionBased = function() {
    // Derive from dimension fields presence
    return this.required_length !== null && 
           this.required_width !== null && 
           this.dimension_unit !== null;
  };

  BOMItem.prototype.isQuantityBased = function() {
    // Derive from quantity field presence
    return this.quantity_per_unit !== null && this.quantity_per_unit !== undefined;
  };

  // Get use_dimensions from associated product (if loaded)
  BOMItem.prototype.getUseDimensions = function() {
    // If product is loaded, use its track_by_dimensions
    if (this.rawMaterial && this.rawMaterial.track_by_dimensions !== undefined) {
      return this.rawMaterial.track_by_dimensions;
    }
    // Otherwise, derive from field presence (backward compatible)
    return this.isDimensionBased();
  };

  BOMItem.prototype.canFitInPiece = function(pieceLength, pieceWidth, pieceUnit = 'm') {
    if (!this.use_dimensions) {
      return null; // Cannot determine for quantity-based items
    }
    
    // For simplicity, assume same unit (unit conversion would be added later)
    if (pieceUnit !== this.dimension_unit) {
      return null; // Unit conversion needed
    }
    
    return pieceLength >= this.required_length && pieceWidth >= this.required_width;
  };

  // Return BOMItem model
  return BOMItem;
};

