/**
 * @fileoverview Utility module for BaseGameValidator.test.js
 * 
 * @module shared.__tests__.BaseGameValidator.test
 */

import { describe, it, expect, vi, beforeEach } from "vitest";
import { BaseGameValidator } from "../BaseGameValidator";

// Subclasse Fake apenas para testar a Base sem depender do MoleMash
class TestValidator extends BaseGameValidator {
  validatePhase(_history, _config, _gameConfig) {
    // Simula uma validação específica que sempre passa se chegar aqui
    return this.success();
  }
}

describe("BaseGameValidator", () => {
  let validator;
  const mockGameConfig = {
    mensagens: {
      semMovimento: "Nada feito",
      caminhoErrado: "Caminho ruim",
      foraTabuleiro: "Saiu da borda",
    },
  };

  beforeEach(() => {
    validator = new TestValidator();
  });

  describe("1. Fail-Safe (Configuração)", () => {
    it("deve falhar se a config da fase for undefined", () => {
      const result = validator.validate([], undefined, mockGameConfig);
      expect(result.success).toBe(false);
      expect(result.reason).toContain("Erro Técnico");
    });

    it("deve falhar se a config da fase for vazia", () => {
      const result = validator.validate([], {}, mockGameConfig);
      expect(result.success).toBe(false);
      expect(result.reason).toContain("Erro Técnico");
    });
  });

  describe("2. Sanity Check (Histórico Vazio)", () => {
    it("deve falhar se o histórico for vazio", () => {
      const result = validator.validate([], { id: 1 }, mockGameConfig);
      expect(result.success).toBe(false);
      expect(result.reason).toBe("Nada feito");
    });

    it("deve falhar se o histórico for null", () => {
      const result = validator.validate(null, { id: 1 }, mockGameConfig);
      expect(result.success).toBe(false);
    });
  });

  describe("3. Validação de Sequência (ExpectedSequence)", () => {
    const configSequencia = {
      id: 1,
      expectedSequence: [
        { l: 1, c: 1 },
        { l: 1, c: 2 },
      ],
    };

    it("deve passar se o histórico bater com a sequência", () => {
      const history = [
        { l: 1, c: 1, t: 100 }, // t (tempo) deve ser ignorado na comparação
        { l: 1, c: 2, t: 200 },
      ];
      const result = validator.validate(
        history,
        configSequencia,
        mockGameConfig,
      );
      expect(result.success).toBe(true);
    });

    it("deve falhar se um passo for diferente", () => {
      const history = [
        { l: 1, c: 1 },
        { l: 1, c: 3 }, // Errado
      ];
      const result = validator.validate(
        history,
        configSequencia,
        mockGameConfig,
      );
      expect(result.success).toBe(false);
      expect(result.reason).toBe("Caminho ruim");
    });

    it("deve falhar se o tamanho for menor que a sequência", () => {
      const history = [{ l: 1, c: 1 }];
      const result = validator.validate(
        history,
        configSequencia,
        mockGameConfig,
      );
      expect(result.success).toBe(false);
    });
  });

  describe("4. Delegação (Template Method)", () => {
    it("deve chamar validatePhase se passar nas validações básicas", () => {
      // Espiona o método da subclasse
      const spy = vi.spyOn(validator, "validatePhase");

      const history = [{ x: 1 }];
      const config = { id: 99 }; // Sem sequence, deve ir pro validatePhase

      const result = validator.validate(history, config, mockGameConfig);

      expect(result.success).toBe(true);
      expect(spy).toHaveBeenCalledWith(history, config, mockGameConfig, undefined);
    });
  });
});
