import { LitElement, html, css } from "lit";
import { gameStateManager } from "../core/GameStateManager.js";
import { GameLoop } from "../core/GameLoop.js";

import "./deployment-hud.js";
import "./dialogue-overlay.js";
import "./combat-hud.js";

export class GameViewport extends LitElement {
  static styles = css`
    :host {
      display: block;
      width: 100%;
      height: 100%;
      overflow: hidden;
    }
    #canvas-container {
      width: 100%;
      height: 100%;
    }
  `;

  static get properties() {
    return {
      squad: { type: Array },
      deployedIds: { type: Array },
      combatState: { type: Object },
      missionDef: { type: Object },
      debriefResult: { type: Object },
    };
  }

  constructor() {
    super();
    this.squad = [];
    this.deployedIds = [];
    this.combatState = null;
    this.missionDef = null;
    this.debriefResult = null;

    // Set up event listeners early so we don't miss events
    this.#setupCombatStateUpdates();
  }

  #handleUnitSelected(event) {
    const unit = event.detail.unit;
    const index = this.squad.indexOf(unit);
    gameStateManager.gameLoop.selectDeploymentUnit(index);
  }

  #handleStartBattle() {
    if (gameStateManager.gameLoop) {
      gameStateManager.gameLoop.finalizeDeployment().catch(console.error);
    }
  }

  #handleEndTurn() {
    if (gameStateManager.gameLoop) {
      gameStateManager.gameLoop.endTurn();
    }
  }

  #handleSkillClick(event) {
    const { skillId } = event.detail;
    if (gameStateManager.gameLoop) {
      gameStateManager.gameLoop.onSkillClicked(skillId);
    }
  }

  #handleMovementClick() {
    if (gameStateManager.gameLoop) {
      gameStateManager.gameLoop.onMovementClicked();
    }
  }

  async firstUpdated() {
    // Only init if connected
    if (!this.isConnected) return;

    if (this.loop) {
      console.warn("GameViewport: Loop already exists, skipping init");
      return;
    }

    const container = this.shadowRoot.getElementById("canvas-container");
    this.loop = new GameLoop();
    this.loop.init(container);
    gameStateManager.setGameLoop(this.loop);

    // Don't set squad from rosterLoaded - that's the full roster, not the current mission squad
    // Squad will be set from activeRunData when transitioning to deployment state

    // Get mission definition for deployment hints (lazy-loaded)
    this.missionDef = null;
    if (gameStateManager.missionManager) {
      gameStateManager.missionManager
        .getActiveMission()
        .then((mission) => {
          this.missionDef = mission || null;
        })
        .catch(console.error);
    }

    // Update squad if activeRunData is already available
    // (in case run-data-updated fired before firstUpdated)
    this.#updateSquad();
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    console.log("GameViewport: disconnectedCallback called");
    if (this.loop) {
      console.log("GameViewport: Disposing GameLoop...");
      this.loop.dispose();
      this.loop = null;
    }
    gameStateManager.disconnectGameLoop();
  }

  #setupCombatStateUpdates() {
    // Listen for combat state changes
    window.addEventListener("combat-state-changed", (e) => {
      this.combatState = e.detail.combatState;
    });

    // Listen for game state changes to update combat state and squad
    window.addEventListener("gamestate-changed", () => {
      this.#updateCombatState();
      this.#updateSquad();
    });

    // Listen for run data updates to get the current mission squad
    window.addEventListener("run-data-updated", (e) => {
      if (e.detail.runData?.squad) {
        // Create a new array reference to ensure LitElement detects the change
        const newSquad = Array.isArray(e.detail.runData.squad)
          ? [...e.detail.runData.squad]
          : [];
        this.squad = newSquad;
        console.log(
          "GameViewport: Squad updated from run-data-updated",
          this.squad.length,
          "units"
        );
      }
    });

    // Listen for mission end events to clear state
    window.addEventListener("mission-victory", () => {
      // Don't clear state immediately - wait for debrief
    });
    window.addEventListener("mission-failure", () => {
      this.#clearState();
    });

    // Listen for show-debrief event
    window.addEventListener("show-debrief", async (e) => {
      // Dynamically import MissionDebrief when needed
      await import("./screens/MissionDebrief.js");
      this.debriefResult = e.detail.result;
    });

    // Listen for debrief-closed event
    window.addEventListener("debrief-closed", () => {
      this.debriefResult = null;
      this.#clearState();
    });

    // Initial updates
    this.#updateCombatState();
    this.#updateSquad();
  }

  #clearState() {
    // Clear squad and deployed IDs when mission ends
    this.squad = [];
    this.deployedIds = [];
    this.combatState = null;
    this.missionDef = null;
    console.log("GameViewport: State cleared after mission end");
  }

  #updateSquad() {
    // Update squad from activeRunData if available (current mission squad, not full roster)
    if (gameStateManager.activeRunData?.squad) {
      // Create a new array reference to ensure LitElement detects the change
      const newSquad = Array.isArray(gameStateManager.activeRunData.squad)
        ? [...gameStateManager.activeRunData.squad]
        : [];
      this.squad = newSquad;
      console.log(
        "GameViewport: Squad updated from activeRunData",
        this.squad.length,
        "units"
      );
    } else {
      console.log("GameViewport: No activeRunData.squad available yet", {
        hasActiveRunData: !!gameStateManager.activeRunData,
        currentSquadLength: this.squad.length,
      });
    }
  }

  #updateCombatState() {
    // Get combat state from GameStateManager
    this.combatState = gameStateManager.getCombatState();
  }

  render() {
    return html`<div id="canvas-container"></div>
      <deployment-hud
        .squad=${this.squad}
        .deployedIds=${this.deployedIds}
        .missionDef=${this.missionDef}
        @unit-selected=${this.#handleUnitSelected}
        @start-battle=${this.#handleStartBattle}
      ></deployment-hud>
      <combat-hud
        .combatState=${this.combatState}
        @end-turn=${this.#handleEndTurn}
        @skill-click=${this.#handleSkillClick}
        @movement-click=${this.#handleMovementClick}
      ></combat-hud>
      <dialogue-overlay></dialogue-overlay>
      ${this.debriefResult
        ? html`<mission-debrief
            .result=${this.debriefResult}
            @return-to-hub=${() => {
              window.dispatchEvent(
                new CustomEvent("debrief-closed", {
                  bubbles: true,
                  composed: true,
                })
              );
            }}
          ></mission-debrief>`
        : html``}`;
  }
}

customElements.define("game-viewport", GameViewport);
