import Phaser from "phaser";
import { type World, type EntityId, type Stats } from "../core/types";
import { GAME_CONFIG } from "../core/config/GameConfig";

export default class GameUI extends Phaser.Scene {
  // HUD
  private floorText!: Phaser.GameObjects.Text;
  private healthBar!: Phaser.GameObjects.Graphics;
  private expBar!: Phaser.GameObjects.Graphics;


  // Menu
  private menuOpen = false;
  private menuContainer!: Phaser.GameObjects.Container;
  private menuText!: Phaser.GameObjects.Text;
  private menuBg!: Phaser.GameObjects.Rectangle;
  private menuButton!: Phaser.GameObjects.Container;
  private mapButton!: Phaser.GameObjects.Container;

  // Death Screen
  private deathContainer!: Phaser.GameObjects.Container;
  private deathText!: Phaser.GameObjects.Text;
  private restartButton!: Phaser.GameObjects.Container;

  constructor() {
    super({ key: "GameUI" });
  }

  create() {
    this.createHud();
    this.createMenu();
    this.createDeathScreen();

    // Listen for updates from GameScene
    const gameScene = this.scene.get("GameScene");
    gameScene.events.on("update-ui", (data: { world: World; playerId: EntityId; floorIndex: number }) => {
      this.updateUI(data.world, data.playerId, data.floorIndex);
    });

    gameScene.events.on("toggle-menu", () => this.toggleMenu());
    gameScene.events.on("close-menu", () => this.setMenuOpen(false));
  }

  private createHud() {
    this.floorText = this.add.text(10, 10, "Floor 1", {
        fontSize: "20px",
        color: "#ffffff",
        fontStyle: "bold"
    }).setDepth(100);

    this.healthBar = this.add.graphics().setDepth(100);
    this.expBar = this.add.graphics().setDepth(100);
  }

  private createMenu() {
    const cam = this.cameras.main;

    const btnW = 90;
    const btnH = 28;

    // Menu Button
    const btnBg = this.add.rectangle(0, 0, btnW, btnH, 0x000000, 0.6).setStrokeStyle(1, 0xffffff, 0.8);
    const btnLabel = this.add.text(0, 0, "Menu", { fontSize: "14px", color: "#ffffff" }).setOrigin(0.5);

    this.menuButton = this.add.container(0, 0, [btnBg, btnLabel]);
    this.menuButton.setDepth(1000);

    const placeButton = () => {
      this.menuButton.setPosition(cam.width - btnW / 2 - 10, btnH / 2 + 10);
    };
    placeButton();
    this.scale.on("resize", placeButton);

    btnBg.setInteractive({ useHandCursor: true }).on("pointerdown", () => this.toggleMenu());

    // Map Button (left of Menu button)
    const mapBtnBg = this.add.rectangle(0, 0, btnW, btnH, 0x000000, 0.6).setStrokeStyle(1, 0xffffff, 0.8);
    const mapBtnLabel = this.add.text(0, 0, "Map", { fontSize: "14px", color: "#ffffff" }).setOrigin(0.5);

    this.mapButton = this.add.container(0, 0, [mapBtnBg, mapBtnLabel]);
    this.mapButton.setDepth(1000);

    const placeMapButton = () => {
      this.mapButton.setPosition(cam.width - btnW / 2 - 10 - btnW - 5, btnH / 2 + 10);
    };
    placeMapButton();
    this.scale.on("resize", placeMapButton);

    mapBtnBg.setInteractive({ useHandCursor: true }).on("pointerdown", () => this.toggleMap());

    // Panel (center)
    const panelW = GAME_CONFIG.ui.menuPanelWidth;
    const panelH = GAME_CONFIG.ui.menuPanelHeight;

    this.menuBg = this.add
      .rectangle(0, 0, panelW, panelH, 0x000000, 0.8)
      .setStrokeStyle(1, 0xffffff, 0.9)
      .setInteractive(); // capture clicks

    this.menuText = this.add
      .text(-panelW / 2 + 14, -panelH / 2 + 12, "", {
        fontSize: "14px",
        color: "#ffffff",
        wordWrap: { width: panelW - 28 }
      })
      .setOrigin(0, 0);

    this.menuContainer = this.add.container(0, 0, [this.menuBg, this.menuText]);
    this.menuContainer.setDepth(1001);

    const placePanel = () => {
      this.menuContainer.setPosition(cam.width / 2, cam.height / 2);
    };
    placePanel();
    this.scale.on("resize", placePanel);

    this.setMenuOpen(false);
  }

  private createDeathScreen() {
    const cam = this.cameras.main;
    const panelW = GAME_CONFIG.ui.menuPanelWidth + 40;
    const panelH = GAME_CONFIG.ui.menuPanelHeight + 60;

    const bg = this.add
      .rectangle(0, 0, cam.width, cam.height, 0x000000, 0.85)
      .setOrigin(0)
      .setInteractive();

    const panel = this.add
      .rectangle(cam.width / 2, cam.height / 2, panelW, panelH, 0x000000, 0.9)
      .setStrokeStyle(2, 0xff3333, 1);

    const title = this.add
      .text(cam.width / 2, cam.height / 2 - panelH / 2 + 30, "YOU HAVE PERISHED", {
        fontSize: "28px",
        color: "#ff3333",
        fontStyle: "bold"
      })
      .setOrigin(0.5);

    this.deathText = this.add
      .text(cam.width / 2, cam.height / 2 - 20, "", {
        fontSize: "16px",
        color: "#ffffff",
        align: "center",
        lineSpacing: 10
      })
      .setOrigin(0.5);

    // Restart Button
    const btnW = 160;
    const btnH = 40;
    const btnBg = this.add.rectangle(0, 0, btnW, btnH, 0x440000, 1).setStrokeStyle(2, 0xff3333, 1);
    const btnLabel = this.add.text(0, 0, "NEW GAME", { fontSize: "18px", color: "#ffffff", fontStyle: "bold" }).setOrigin(0.5);
    
    this.restartButton = this.add.container(cam.width / 2, cam.height / 2 + panelH / 2 - 50, [btnBg, btnLabel]);
    btnBg.setInteractive({ useHandCursor: true }).on("pointerdown", () => {
        const gameScene = this.scene.get("GameScene");
        gameScene.events.emit("restart-game");
        this.hideDeathScreen();
    });

    this.deathContainer = this.add.container(0, 0, [bg, panel, title, this.deathText, this.restartButton]);
    this.deathContainer.setDepth(2000);
    this.deathContainer.setVisible(false);
  }

  showDeathScreen(data: { floor: number; gold: number; stats: Stats }) {
    const lines = [
      `Dungeon Floor: ${data.floor}`,
      `Gold Collected: ${data.gold}`,

      "",
      `Experience gained: ${data.stats.exp}`,
      `Final HP: 0 / ${data.stats.maxHp}`,
      `Attack: ${data.stats.attack}`,
      `Defense: ${data.stats.defense}`
    ];
    this.deathText.setText(lines.join("\n"));
    this.deathContainer.setVisible(true);
    
    // Disable other UI interactions
    this.menuButton.setVisible(false);
    this.mapButton.setVisible(false);
  }

  hideDeathScreen() {
    this.deathContainer.setVisible(false);
    this.menuButton.setVisible(true);
    this.mapButton.setVisible(true);
  }

  private toggleMenu() {
    this.setMenuOpen(!this.menuOpen);
    // Request UI update when menu is opened to populate the text
    if (this.menuOpen) {
      const gameScene = this.scene.get("GameScene");
      gameScene.events.emit("request-ui-update");
    }
  }

  private setMenuOpen(open: boolean) {
    this.menuOpen = open;
    this.menuContainer.setVisible(open);
    
    // Notify GameScene back?
    const gameScene = this.scene.get("GameScene");
    gameScene.events.emit("menu-toggled", open);
  }

  private toggleMap() {
    // Close menu and toggle minimap
    this.setMenuOpen(false);
    const gameScene = this.scene.get("GameScene");
    gameScene.events.emit("toggle-minimap");
  }

  private updateUI(world: World, playerId: EntityId, floorIndex: number) {
    this.updateHud(world, playerId, floorIndex);
    if (this.menuOpen) {
      this.updateMenuText(world, playerId, floorIndex);
    }
  }

  private updateHud(world: World, playerId: EntityId, floorIndex: number) {
    this.floorText.setText(`Floor ${floorIndex}`);


    const p = world.actors.get(playerId);
    if (!p || !p.stats) return;

    const barX = 40;
    const barY = 40;
    const barW = 180;
    const barH = 16;
    
    this.healthBar.clear();
    
    // Heart Icon
    const iconX = 20;
    const iconY = barY + barH / 2;
    this.healthBar.fillStyle(0xff0000, 1);
    // Draw simple heart
    this.healthBar.fillCircle(iconX - 4, iconY - 2, 5);
    this.healthBar.fillCircle(iconX + 4, iconY - 2, 5);
    this.healthBar.fillTriangle(iconX - 9, iconY - 1, iconX + 9, iconY - 1, iconX, iconY + 9);

    this.healthBar.fillStyle(0x444444, 1);
    this.healthBar.fillRect(barX, barY, barW, barH);


    const hp = Math.max(0, p.stats.hp);
    const maxHp = Math.max(1, p.stats.maxHp);
    const pct = Phaser.Math.Clamp(hp / maxHp, 0, 1);
    const fillW = Math.floor(barW * pct);

    this.healthBar.fillStyle(0xff0000, 1);
    this.healthBar.fillRect(barX, barY, fillW, barH);
    
    this.healthBar.lineStyle(2, 0xffffff, 1);
    this.healthBar.strokeRect(barX, barY, barW, barH);

    // EXP Bar
    const expY = barY + barH + 6;
    const expH = 10;
    this.expBar.clear();

    // EXP Icon (Star/Orb)
    const expIconY = expY + expH / 2;
    this.expBar.fillStyle(GAME_CONFIG.rendering.expOrbColor, 1);
    this.expBar.fillCircle(iconX, expIconY, 6);
    this.expBar.fillStyle(0xffffff, 0.5);
    this.expBar.fillCircle(iconX - 2, expIconY - 2, 2);

    this.expBar.fillStyle(0x444444, 1);
    this.expBar.fillRect(barX, expY, barW, expH);

    const exp = p.stats.exp;
    const nextExp = Math.max(1, p.stats.expToNextLevel);

    const expPct = Phaser.Math.Clamp(exp / nextExp, 0, 1);
    const expFillW = Math.floor(barW * expPct);

    this.expBar.fillStyle(GAME_CONFIG.rendering.expOrbColor, 1);
    this.expBar.fillRect(barX, expY, expFillW, expH);
    
    this.expBar.lineStyle(1, 0xffffff, 0.8);
    this.expBar.strokeRect(barX, expY, barW, expH);

  }


  private updateMenuText(world: World, playerId: EntityId, _floorIndex: number) {


    const p = world.actors.get(playerId);
    const stats = p?.stats;
    const inv = p?.inventory;

    const lines: string[] = [];
    lines.push(`Level ${stats?.level ?? 1}`);
    lines.push("");
    lines.push("Stats");
    lines.push(`  HP: ${stats?.hp ?? 0}/${stats?.maxHp ?? 0}`);
    lines.push(`  EXP: ${stats?.exp ?? 0}/${stats?.expToNextLevel ?? 0}`);
    lines.push(`  Attack: ${stats?.attack ?? 0}`);
    lines.push(`  Defense: ${stats?.defense ?? 0}`);
    lines.push(`  Speed: ${p?.speed ?? 0}`);

    lines.push("");
    lines.push("Inventory");
    lines.push(`  Gold: ${inv?.gold ?? 0}`);
    lines.push(`  Items: ${(inv?.items?.length ?? 0) === 0 ? "(none)" : ""}`);

    if (inv?.items?.length) {
      for (const it of inv.items) lines.push(`   - ${it}`);
    }

    lines.push("");
    lines.push("Hotkeys: I to toggle, Esc to close");

    this.menuText.setText(lines.join("\n"));
  }
}
