import type { World, CombatantActor, Item, ItemDropActor, Vec2 } from "../../core/types";
import { EntityManager } from "../../engine/EntityManager";

/**
 * Result of attempting to use an item
 */
export interface ItemUseResult {
  success: boolean;
  consumed: boolean;
  message?: string;
}

/**
 * Manages item-related operations including spawning, pickup, and usage.
 * Extracted from GameScene to centralize item logic and reduce complexity.
 */
export class ItemManager {
  private world: World;
  private entityManager: EntityManager;

  constructor(world: World, entityManager: EntityManager) {
    this.world = world;
    this.entityManager = entityManager;
  }

  /**
   * Update references when world changes (e.g., new floor)
   */
  updateWorld(world: World, entityManager: EntityManager): void {
    this.world = world;
    this.entityManager = entityManager;
  }

  /**
   * Spawn an item drop at the specified position
   */
  spawnItem(item: Item, pos: Vec2): void {
    if (!this.world || !this.entityManager) return;
    
    const id = this.entityManager.getNextId();
    const drop: ItemDropActor = {
      id,
      pos: { x: pos.x, y: pos.y },
      category: "item_drop",
      item: { ...item } // Clone item
    };
    
    this.entityManager.addActor(drop);
  }

  /**
   * Try to pickup an item at the player's position
   * @returns The picked up item, or null if nothing to pick up
   */
  tryPickup(player: CombatantActor): Item | null {
    if (!player || !player.inventory) return null;

    const actors = this.entityManager.getActorsAt(player.pos.x, player.pos.y);
    const itemActor = actors.find((a): a is ItemDropActor => a.category === "item_drop");

    if (itemActor) {
      const item = itemActor.item;
      
      // Add to inventory
      player.inventory.items.push(item);
      
      // Remove from world
      this.entityManager.removeActor(itemActor.id);
      
      console.log("Picked up:", item.name);
      return item;
    }

    return null;
  }

  /**
   * Handle using an item from inventory
   * Returns information about what happened
   */
  handleUse(itemId: string, player: CombatantActor): ItemUseResult {
    if (!player || !player.inventory) {
      return { success: false, consumed: false, message: "Invalid player state" };
    }

    const itemIdx = player.inventory.items.findIndex(it => it.id === itemId);
    if (itemIdx === -1) {
      return { success: false, consumed: false, message: "Item not found" };
    }

    const item = player.inventory.items[itemIdx];

    // Check if item is a healing consumable
    if (item.stats && item.stats.hp && item.stats.hp > 0) {
      const healAmount = item.stats.hp;
      
      if (player.stats.hp >= player.stats.maxHp) {
        return { success: false, consumed: false, message: "Already at full health" };
      }

      player.stats.hp = Math.min(player.stats.hp + healAmount, player.stats.maxHp);
      
      // Remove item after use
      player.inventory.items.splice(itemIdx, 1);
      
      return { 
        success: true, 
        consumed: true, 
        message: `Healed for ${healAmount} HP` 
      };
    }

    // Throwable items are handled by TargetingSystem, not here
    if (item.throwable) {
      return { 
        success: true, 
        consumed: false, 
        message: "Throwable item - use targeting" 
      };
    }

    return { 
      success: false, 
      consumed: false, 
      message: "Item has no effect" 
    };
  }

  /**
   * Remove an item from player inventory by ID
   */
  removeFromInventory(player: CombatantActor, itemId: string): boolean {
    if (!player || !player.inventory) return false;

    const itemIdx = player.inventory.items.findIndex(it => it.id === itemId);
    if (itemIdx === -1) return false;

    player.inventory.items.splice(itemIdx, 1);
    return true;
  }

  /**
   * Get an item from player inventory by ID
   */
  getItem(player: CombatantActor, itemId: string): Item | null {
    if (!player || !player.inventory) return null;

    const item = player.inventory.items.find(it => it.id === itemId);
    return item || null;
  }
}
