/**
 * @fileoverview Cena Phaser para o jogo Ordenação.
 * Responsabilidades:
 *   - Renderizar a lista como barras coloridas
 *   - Expor a lista ao interpretador
 *   - Receber atualizações da lista durante a execução
 */

import Phaser from "phaser";
import { BaseGameScene } from "../../../shared/BaseGameScene.js";
import { setupOrdenacaoAPI } from "./hooks/interpreterSetup.js";
import { validationSolution } from "./validation/validators.js";
import { gameConfig } from "./config/config.js";
import { ConstantesJogo, BAR_W, MIN_H, MAX_H, GROUND_Y, Cores } from "./ui/constants.js";

const { LARGURA_TELA: W, ALTURA_TELA: H } = ConstantesJogo;
const BAR_GAP = 20;
const SPACING = BAR_W + BAR_GAP;
const DELAY_COMPARE_MS = 70;
const DELAY_WRITE_MS = 90;
const DELAY_SWAP_MS = 170;

class OrdenacaoScene extends BaseGameScene {
  constructor() {
    super("OrdenacaoScene");
    this.lista = [];
    this.contagem = [];
    this.listaInicial = [];
    this.barras = [];
    this._labelResultado = null;
    this._passos = 0;
    this._segundos = 0;
    this._timerEvento = null;
    this._timeDisplay = null;
    this._stepsDisplay = null;
  }

  init(data) {
    super.init(data);
    this.listaInicial = [...(this.configFase?.lista ?? [2, 1])];
    this.lista = [...this.listaInicial];
  }

  preload() {
    this.preloadGlobalAssets();
  }

  create() {
    this.setupStandardController(
      setupOrdenacaoAPI,
      (historico) => validationSolution(historico, this.configFase, gameConfig, this)
    );
    this._criarHeaderDom();
    this._criarBarras();
  }

  _criarHeaderDom() {
    const container = document.createElement("div");
    container.innerHTML = `
      <div style="background:#5c3d2e;border:3px solid #3b2010;border-radius:12px;padding:10px 25px;box-shadow:0 8px 0 #2a1a0e,0 15px 20px rgba(0,0,0,0.3);display:flex;gap:40px;pointer-events:none;">
        <div style="display:flex;flex-direction:column;align-items:center;gap:4px;">
          <div style="color:white;font-size:15px;font-weight:bold;text-shadow:2px 2px 0 #3b2010;font-family:sans-serif;">Tempo</div>
          <div id="ord-time" style="background:#111;color:#00ff88;font-size:22px;font-weight:bold;padding:4px 15px;border-radius:8px;border:2px solid #2a1a17;box-shadow:inset 0 5px 10px rgba(0,0,0,0.7),0 2px 0 rgba(255,255,255,0.2);letter-spacing:4px;font-family:monospace;">00:00</div>
        </div>
        <div style="display:flex;flex-direction:column;align-items:center;gap:4px;">
          <div style="color:white;font-size:15px;font-weight:bold;text-shadow:2px 2px 0 #3b2010;font-family:sans-serif;">Passos</div>
          <div id="ord-steps" style="background:#111;color:#00ff88;font-size:22px;font-weight:bold;padding:4px 15px;border-radius:8px;border:2px solid #2a1a17;box-shadow:inset 0 5px 10px rgba(0,0,0,0.7),0 2px 0 rgba(255,255,255,0.2);letter-spacing:4px;font-family:monospace;">0000</div>
        </div>
      </div>
    `;
    this.add.dom(W / 2, 48, container).setDepth(20);
    this._timeDisplay = container.querySelector("#ord-time");
    this._stepsDisplay = container.querySelector("#ord-steps");
  }

  _atualizarDisplays() {
    if (this._timeDisplay) {
      const m = Math.floor(this._segundos / 60).toString().padStart(2, "0");
      const s = (this._segundos % 60).toString().padStart(2, "0");
      this._timeDisplay.textContent = `${m}:${s}`;
    }
    if (this._stepsDisplay) {
      this._stepsDisplay.textContent = String(this._passos).padStart(4, "0");
    }
  }

  _iniciarTimer() {
    this._pararTimer();
    this._timerEvento = this.time.addEvent({
      delay: 1000,
      callback: () => {
        this._segundos++;
        this._atualizarDisplays();
      },
      loop: true,
    });
  }

  _pararTimer() {
    if (this._timerEvento) {
      this._timerEvento.remove();
      this._timerEvento = null;
    }
  }

  _criarBarras() {
    const n = this.lista.length;
    const maxVal = Math.max(...this.lista);
    const minVal = Math.min(...this.lista);
    const range = maxVal - minVal || 1;
    const totalW = n * BAR_W + (n - 1) * BAR_GAP;
    const startX = (W - totalW) / 2 + BAR_W / 2;

    this.barras = this.lista.map((valor, i) => {
      const x = startX + i * SPACING;
      const height = MIN_H + ((valor - minVal) / range) * (MAX_H - MIN_H);
      const hue = (valor / (maxVal + 1)) * 0.72;
      const color = Phaser.Display.Color.HSVToRGB(hue, 0.85, 0.92).color;
      const container = this.add.container(x, GROUND_Y);
      const rect = this.add.rectangle(0, -height / 2, BAR_W, height, color)
        .setStrokeStyle(2, Cores.BORDA_PADRAO);
      const numLabel = this.add.text(0, -height - 14, String(valor), {
        fontSize: "22px", fontFamily: "Arial Black, sans-serif", color: "#FFFFFF",
        stroke: "#222222", strokeThickness: 4,
      }).setOrigin(0.5, 1);
      const idxLabel = this.add.text(0, 14, String(i), {
        fontSize: "13px", fontFamily: "Arial, sans-serif", color: "#E8E8E8",
      }).setOrigin(0.5, 0.5);
      container.add([rect, numLabel, idxLabel]);
      return { container, rect, numLabel, idxLabel, valor };
    });
  }

  _recriarBarras() {
    this.tweens.killAll();
    this.barras.forEach((b) => b.container.destroy());
    this.barras = [];
    this._criarBarras();
  }

  onBeforeRun() {
    this.historico = [];
    this.lista = [...this.listaInicial];
    this._recriarBarras();
    this._limparLabel();
    this._passos = 0;
    this._segundos = 0;
    this._atualizarDisplays();
    this._iniciarTimer();
  }

  onReset() {
    this.lista = [...this.listaInicial];
    this._recriarBarras();
    this.historico = [];
    this._limparLabel();
    this._pararTimer();
    this._passos = 0;
    this._segundos = 0;
    this._atualizarDisplays();
  }

  async onSuccess() {
    this._pararTimer();
    for (let i = 0; i < this.barras.length; i++) {
      this.barras[i].rect.setFillStyle(Cores.ORDENADO);
      this.barras[i].rect.setStrokeStyle(3, 0xFFFFFF);
      await this._sleep(90);
    }
    this._labelResultado = this.add.text(W / 2, 36, "✓  Lista Ordenada!", {
      fontSize: "26px", fontFamily: "Arial Black, sans-serif",
      color: "#00FF88", stroke: "#003322", strokeThickness: 5,
    }).setOrigin(0.5, 0).setDepth(10);
  }

  async onFailure() {
    this._pararTimer();
    for (const b of this.barras) {
      b.rect.setFillStyle(Cores.ERRO);
    }
    await this._sleep(600);
    this._recriarBarras();
  }

  _setHighlight(index, color) {
    if (!this.barras[index]) return;
    if (color === null) {
      this.barras[index].rect.setStrokeStyle(2, Cores.BORDA_PADRAO);
    } else {
      this.barras[index].rect.setStrokeStyle(4, color);
    }
  }

  async animarComparacao(i, j) {
    this._passos++;
    this._atualizarDisplays();
    this._setHighlight(i, 0xffeb3b);
    this._setHighlight(j, 0xffeb3b);
    await this._sleep(DELAY_COMPARE_MS);
    this._setHighlight(i, null);
    this._setHighlight(j, null);
  }

  async animarEscrita(i) {
    this._passos++;
    this._atualizarDisplays();
    // Recria barras para refletir altura/valor atualizados na lista.
    this._recriarBarras();
    this._setHighlight(i, 0xff9800);
    await this._sleep(DELAY_WRITE_MS);
    this._setHighlight(i, null);
  }

  async animarTroca(i, j) {
    this._passos++;
    this._atualizarDisplays();
    const barraI = this.barras[i];
    const barraJ = this.barras[j];
    if (!barraI || !barraJ || i === j) return;

    this._setHighlight(i, 0xffd54f);
    this._setHighlight(j, 0xffd54f);

    const xI = barraI.container.x;
    const xJ = barraJ.container.x;

    await new Promise((resolve) => {
      let done = 0;
      const onComplete = () => {
        done += 1;
        if (done === 2) resolve();
      };

      this.tweens.add({
        targets: barraI.container,
        x: xJ,
        duration: DELAY_SWAP_MS,
        ease: "Sine.easeInOut",
        onComplete,
      });

      this.tweens.add({
        targets: barraJ.container,
        x: xI,
        duration: DELAY_SWAP_MS,
        ease: "Sine.easeInOut",
        onComplete,
      });
    });

    // Após a animação, reconstrói visual com a ordem atual da lista.
    this._recriarBarras();
  }

  _limparLabel() {
    if (this._labelResultado) {
      this._labelResultado.destroy();
      this._labelResultado = null;
    }
  }

  _sleep(ms) {
    return new Promise((resolve) => this.time.delayedCall(ms, resolve));
  }
}

export const createGame = (elementoPai, configFaseAtual) => {
  const scene = new OrdenacaoScene();
  return {
    type: Phaser.AUTO,
    width: ConstantesJogo.LARGURA_TELA,
    height: ConstantesJogo.ALTURA_TELA,
    backgroundColor: ConstantesJogo.COR_FUNDO,
    parent: elementoPai,
    dom: { createContainer: true },
    scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH },
    scene,
    callbacks: {
      preBoot(game) {
        game.registry.set("configFase", configFaseAtual);
        game.registry.set("gameConfig", gameConfig);
      },
    },
  };
};
