import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { computeGaugeLive, enclosGlobalState } from '@presentation/helpers/gauge-live';
import { createEnclos } from '@domain/entities/Enclos';
import { createDragodinde } from '@domain/entities/Dragodinde';
import type { Enclos } from '@domain/entities/Enclos';
import type { Dragodinde } from '@domain/entities/Dragodinde';

/**
 * Régression : après une recharge de jauge en cours de timer,
 * le countdown (cntDown) doit être fini (pas Infinity).
 *
 * Scénario reproduit : la jauge baffeur se vide complètement,
 * le joueur la recharge → le countdown doit recalculer à partir
 * du nouveau niveau de jauge, pas rester bloqué à ∞.
 */
describe('Régression: countdown fini après recharge de jauge vidée', () => {
  const NOW = 1_700_000_000_000; // timestamp fixe

  beforeEach(() => {
    vi.useFakeTimers();
    vi.setSystemTime(NOW);
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  function buildEnclos(dd: Dragodinde, opts: {
    startGl: number;
    elapsedSec: number;
    recharges?: { atSec: number; level: number }[];
    currentGl: number;
  }): Enclos {
    const enc = createEnclos(1, 'Test');
    enc.activeGauges = ['baffeur'];
    enc.gaugeLevels = { ...enc.gaugeLevels, baffeur: opts.currentGl };
    enc.dragodindes = [dd];
    enc.timer = {
      running: true,
      startTime: NOW - opts.elapsedSec * 1000,
      pausedAt: null,
      pausedMs: 0,
      snapGauges: { baffeur: opts.startGl },
      snapStats: { [dd.id]: { serenite: 0, endurance: 0, maturite: 0, amour: 0, xp: 1 } },
      gaugeRecharges: opts.recharges
        ? { baffeur: opts.recharges }
        : {},
    };
    return enc;
  }

  it('sans recharge et jauge vidée → cntDown est Infinity', () => {
    const dd = createDragodinde(1);
    // Jauge baffeur départ = 100, elapsed = 200s → largement vidée (100 pts = tier1 10/tick)
    // timeToGain(100, 100) = ceil(100/10)*10 = 100s → à 200s la jauge est à 0
    const enc = buildEnclos(dd, {
      startGl: 100,
      elapsedSec: 200,
      currentGl: 0,
    });

    const result = computeGaugeLive(enc, dd, 'baffeur', 200, true);

    expect(result.curGl).toBe(0);
    expect(result.cntDown).toBe(Infinity);
  });

  it('après recharge de la jauge vidée → cntDown est fini et > 0', () => {
    const dd = createDragodinde(1);
    // Jauge baffeur départ = 100, elapsed = 200s
    // Recharge à t=150s avec niveau 50000
    // À t=200s, la jauge a été rechargée et n'est plus à 0
    const enc = buildEnclos(dd, {
      startGl: 100,
      elapsedSec: 200,
      recharges: [{ atSec: 150, level: 50000 }],
      currentGl: 50000,
    });

    const result = computeGaugeLive(enc, dd, 'baffeur', 200, true);

    // La jauge rechargée à 50000 a eu 50s pour se vider (200-150)
    // Elle doit être > 0 (50000 pts se vide en bien plus de 50s)
    expect(result.curGl).toBeGreaterThan(0);

    // Le countdown doit être fini (pas Infinity) et positif
    expect(isFinite(result.cntDown)).toBe(true);
    expect(result.cntDown).toBeGreaterThan(0);
  });

  it('enclosGlobalState retourne un globalMax fini après recharge', () => {
    const dd = createDragodinde(1);
    const enc = buildEnclos(dd, {
      startGl: 100,
      elapsedSec: 200,
      recharges: [{ atSec: 150, level: 50000 }],
      currentGl: 50000,
    });

    const state = enclosGlobalState(enc);

    expect(state.started).toBe(true);
    expect(isFinite(state.globalMax)).toBe(true);
    expect(state.globalMax).toBeGreaterThan(0);
  });
});
