import type { GameScene } from "../GameScene";
import type { DungeonRenderer } from "../../rendering/DungeonRenderer";
import type { CombatantActor } from "../../core/types";
import type { ProgressionManager } from "../../engine/ProgressionManager";
import type { ItemManager } from "./ItemManager";
import type { TargetingSystem } from "./TargetingSystem";

/**
 * Centralizes all event handling between GameScene and UI.
 * Extracted from GameScene to reduce complexity and make event flow clearer.
 */
export class EventBridge {
  private scene: GameScene;

  constructor(scene: GameScene) {
    this.scene = scene;
  }

  /**
   * Set up all event listeners
   */
  setupListeners(
    dungeonRenderer: DungeonRenderer,
    progressionManager: ProgressionManager,
    itemManager: ItemManager,
    targetingSystem: TargetingSystem,
    awaitingPlayerFn: () => boolean,
    commitActionFn: (action: any) => void,
    emitUIUpdateFn: () => void,
    restartGameFn: () => void,
    executeThrowFn: (x: number, y: number) => void
  ): void {
    // Menu state listeners (from UI)
    this.scene.events.on("menu-toggled", (isOpen: boolean) => {
      (this.scene as any).isMenuOpen = isOpen;
    });

    this.scene.events.on("inventory-toggled", (isOpen: boolean) => {
      (this.scene as any).isInventoryOpen = isOpen;
    });

    this.scene.events.on("character-toggled", (isOpen: boolean) => {
      (this.scene as any).isCharacterOpen = isOpen;
    });

    // Minimap toggle
    this.scene.events.on("toggle-minimap", () => {
      dungeonRenderer.toggleMinimap();
    });

    // UI update requests
    this.scene.events.on("request-ui-update", () => {
      emitUIUpdateFn();
    });

    // Game restart
    this.scene.events.on("restart-game", () => {
      restartGameFn();
    });

    // Stat allocation
    this.scene.events.on("allocate-stat", (statName: string) => {
      const player = (this.scene as any).world.actors.get((this.scene as any).playerId) as CombatantActor;
      if (player) {
        progressionManager.allocateStat(player, statName);
        emitUIUpdateFn();
      }
    });

    // Passive allocation
    this.scene.events.on("allocate-passive", (nodeId: string) => {
      const player = (this.scene as any).world.actors.get((this.scene as any).playerId) as CombatantActor;
      if (player) {
        progressionManager.allocatePassive(player, nodeId);
        emitUIUpdateFn();
      }
    });

    // Player wait action
    this.scene.events.on("player-wait", () => {
      if (!awaitingPlayerFn()) return;
      if ((this.scene as any).isMenuOpen || (this.scene as any).isInventoryOpen || dungeonRenderer.isMinimapVisible()) return;
      commitActionFn({ type: "wait" });
    });

    // Player search action
    this.scene.events.on("player-search", () => {
      if (!awaitingPlayerFn()) return;
      if ((this.scene as any).isMenuOpen || (this.scene as any).isInventoryOpen || dungeonRenderer.isMinimapVisible()) return;
      console.log("Player searching...");
      commitActionFn({ type: "wait" });
    });

    // Item use
    this.scene.events.on("use-item", (data: { itemId: string }) => {
      if (!awaitingPlayerFn()) return;

      const player = (this.scene as any).world.actors.get((this.scene as any).playerId) as CombatantActor;
      if (!player || !player.inventory) return;

      const itemIdx = player.inventory.items.findIndex(it => it.id === data.itemId);
      if (itemIdx === -1) return;
      const item = player.inventory.items[itemIdx];

      const result = itemManager.handleUse(data.itemId, player);

      if (result.success && result.consumed) {
        const healAmount = player.stats.maxHp - player.stats.hp;
        const actualHeal = Math.min(healAmount, player.stats.hp);
        dungeonRenderer.showHeal(player.pos.x, player.pos.y, actualHeal);
        commitActionFn({ type: "wait" });
        emitUIUpdateFn();
      } else if (result.success && !result.consumed) {
        // Throwable item - start targeting
        if (targetingSystem.isActive && targetingSystem.itemId === item.id) {
          // Already targeting - execute throw
          if (targetingSystem.cursorPos) {
            executeThrowFn(targetingSystem.cursorPos.x, targetingSystem.cursorPos.y);
          }
          return;
        }

        targetingSystem.startTargeting(
          item.id,
          player.pos,
          (this.scene as any).world,
          dungeonRenderer.seenArray,
          (this.scene as any).world.width
        );
        emitUIUpdateFn();
      }
    });
  }

  /**
   * Clean up all event listeners (call on scene shutdown)
   */
  cleanup(): void {
    this.scene.events.removeAllListeners("menu-toggled");
    this.scene.events.removeAllListeners("inventory-toggled");
    this.scene.events.removeAllListeners("character-toggled");
    this.scene.events.removeAllListeners("toggle-minimap");
    this.scene.events.removeAllListeners("request-ui-update");
    this.scene.events.removeAllListeners("restart-game");
    this.scene.events.removeAllListeners("allocate-stat");
    this.scene.events.removeAllListeners("allocate-passive");
    this.scene.events.removeAllListeners("player-wait");
    this.scene.events.removeAllListeners("player-search");
    this.scene.events.removeAllListeners("use-item");
  }
}
