const mongoose = require('mongoose');

const inventorySchema = new mongoose.Schema({
  userId: {
    type: String,
    required: true,
    ref: 'Player'
  },
  
  // Inventory settings
  maxSlots: {
    type: Number,
    default: 50
  },
  
  // Items array
  items: [{
    id: {
      type: String,
      required: true
    },
    name: {
      type: String,
      required: true
    },
    type: {
      type: String,
      required: true,
      enum: ['weapon', 'armor', 'material', 'consumable']
    },
    rarity: {
      type: String,
      enum: ['common', 'uncommon', 'rare', 'epic', 'legendary'],
      default: 'common'
    },
    quantity: {
      type: Number,
      default: 1,
      min: 1
    },
    
    // Item stats (for weapons/armor)
    stats: {
      attack: { type: Number, default: 0 },
      defense: { type: Number, default: 0 },
      speed: { type: Number, default: 0 },
      criticalChance: { type: Number, default: 0 },
      criticalDamage: { type: Number, default: 1.5 },
      damage: { type: Number, default: 0 },
      fireRate: { type: Number, default: 0 },
      range: { type: Number, default: 0 },
      energy: { type: Number, default: 0 },
      health: { type: Number, default: 0 },
      maxHealth: { type: Number, default: 0 },
      durability: { type: Number, default: 0 },
      weight: { type: Number, default: 0 },
      energyShield: { type: Number, default: 0 }
    },
    
    // Item properties
    description: {
      type: String,
      default: ''
    },
    
    // Equipment properties
    equipable: {
      type: Boolean,
      default: false
    },
    slot: {
      type: String,
      enum: ['weapon', 'armor', 'engine', 'shield', 'special'],
      default: null
    },
    isEquipped: {
      type: Boolean,
      default: false
    },
    
    // Consumable properties
    consumable: {
      type: Boolean,
      default: false
    },
    effect: {
      health: { type: Number, default: 0 },
      energy: { type: Number, default: 0 },
      attack: { type: Number, default: 0 },
      defense: { type: Number, default: 0 },
      speed: { type: Number, default: 0 },
      duration: { type: Number, default: 0 }
    },
    
    // Stackable items
    stackable: {
      type: Boolean,
      default: false
    },
    
    // Timestamps
    acquiredAt: {
      type: Date,
      default: Date.now
    },
    lastUsed: {
      type: Date,
      default: null
    }
  }],
  
  // Equipped items
  equippedItems: {
    weapon: { type: String, default: null },
    armor: { type: String, default: null },
    engine: { type: String, default: null },
    shield: { type: String, default: null },
    special: { type: String, default: null }
  },
  
  // Timestamps
  updatedAt: {
    type: Date,
    default: Date.now
  }
}, {
  timestamps: true
});

// Indexes for performance
inventorySchema.index({ userId: 1 });
inventorySchema.index({ 'items.id': 1 });
inventorySchema.index({ 'items.type': 1 });

// Methods
inventorySchema.methods.addItem = function(itemData) {
  // Check if item already exists and is stackable
  const existingItem = this.items.find(item => 
    item.id === itemData.id && 
    item.type === itemData.type && 
    item.stackable
  );
  
  if (existingItem) {
    existingItem.quantity += itemData.quantity || 1;
  } else {
    // Add new item
    const newItem = {
      ...itemData,
      quantity: itemData.quantity || 1,
      acquiredAt: new Date()
    };
    
    this.items.push(newItem);
  }
  
  this.updatedAt = new Date();
  return this.save();
};

inventorySchema.methods.removeItem = function(itemId, quantity = 1) {
  const itemIndex = this.items.findIndex(item => item.id === itemId);
  
  if (itemIndex === -1) {
    throw new Error('Item not found in inventory');
  }
  
  const item = this.items[itemIndex];
  
  if (item.quantity > quantity) {
    item.quantity -= quantity;
  } else {
    // Remove item completely
    this.items.splice(itemIndex, 1);
    
    // Unequip if it was equipped
    Object.keys(this.equippedItems).forEach(slot => {
      if (this.equippedItems[slot] === itemId) {
        this.equippedItems[slot] = null;
      }
    });
  }
  
  this.updatedAt = new Date();
  return this.save();
};

inventorySchema.methods.hasItem = function(itemId, quantity = 1) {
  const item = this.items.find(item => item.id === itemId);
  return item && item.quantity >= quantity;
};

inventorySchema.methods.getItemCount = function(itemId) {
  const item = this.items.find(item => item.id === itemId);
  return item ? item.quantity : 0;
};

inventorySchema.methods.equipItem = function(itemId, slot) {
  const item = this.items.find(item => item.id === itemId);
  
  if (!item) {
    throw new Error('Item not found in inventory');
  }
  
  if (!item.equipable) {
    throw new Error('Item is not equipable');
  }
  
  if (item.slot !== slot) {
    throw new Error('Item cannot be equipped in this slot');
  }
  
  // Unequip current item in slot
  if (this.equippedItems[slot]) {
    const currentItem = this.items.find(item => item.id === this.equippedItems[slot]);
    if (currentItem) {
      currentItem.isEquipped = false;
    }
  }
  
  // Equip new item
  this.equippedItems[slot] = itemId;
  item.isEquipped = true;
  item.lastUsed = new Date();
  
  this.updatedAt = new Date();
  return this.save();
};

inventorySchema.methods.unequipItem = function(slot) {
  const itemId = this.equippedItems[slot];
  
  if (!itemId) {
    throw new Error('No item equipped in this slot');
  }
  
  const item = this.items.find(item => item.id === itemId);
  if (item) {
    item.isEquipped = false;
  }
  
  this.equippedItems[slot] = null;
  this.updatedAt = new Date();
  return this.save();
};

inventorySchema.methods.useConsumable = function(itemId) {
  const item = this.items.find(item => item.id === itemId);
  
  if (!item) {
    throw new Error('Item not found in inventory');
  }
  
  if (!item.consumable) {
    throw new Error('Item is not consumable');
  }
  
  if (item.quantity <= 0) {
    throw new Error('No quantity left');
  }
  
  // Apply effects
  const effects = { ...item.effect };
  
  // Remove one from quantity
  item.quantity -= 1;
  item.lastUsed = new Date();
  
  // Remove item if quantity is 0
  if (item.quantity === 0) {
    const itemIndex = this.items.findIndex(item => item.id === itemId);
    this.items.splice(itemIndex, 1);
  }
  
  this.updatedAt = new Date();
  this.save();
  
  return effects;
};

inventorySchema.methods.getInventorySummary = function() {
  const summary = {
    totalItems: this.items.length,
    usedSlots: this.items.length,
    maxSlots: this.maxSlots,
    itemsByType: {},
    equippedItems: this.equippedItems
  };
  
  // Count items by type
  this.items.forEach(item => {
    summary.itemsByType[item.type] = (summary.itemsByType[item.type] || 0) + item.quantity;
  });
  
  return summary;
};

inventorySchema.methods.getItemsByType = function(type) {
  return this.items.filter(item => item.type === type);
};

inventorySchema.methods.getItemsByRarity = function(rarity) {
  return this.items.filter(item => item.rarity === rarity);
};

module.exports = mongoose.model('Inventory', inventorySchema);
