import { describe, expect, it, vi } from 'vitest';
import { EventBus } from '../src/core/EventBus';
import { Meters, freshNightState } from '../src/core/meters';

const setup = () => {
  const bus = new EventBus();
  const state = freshNightState('theRoyal', 0, 80);
  const meters = new Meters(bus, state);
  return { bus, state, meters };
};

describe('Meters', () => {
  it('applies deltas and emits meters:changed', () => {
    const { bus, state } = setup();
    const fn = vi.fn();
    bus.on('meters:changed', fn);
    bus.emit('meters:delta', { vibe: 10, aggro: 5 });
    expect(state.vibe).toBe(60);
    expect(state.aggro).toBe(5);
    expect(fn).toHaveBeenCalledWith({ vibe: 60, aggro: 5, hype: 1 });
  });

  it('clamps vibe/aggro to 0..100 and hype to 1..3', () => {
    const { bus, state } = setup();
    bus.emit('meters:delta', { vibe: 999, aggro: -50, hype: 99 });
    expect(state.vibe).toBe(100);
    expect(state.aggro).toBe(0);
    expect(state.hype).toBe(3);
    bus.emit('meters:delta', { vibe: -999 });
    expect(state.vibe).toBe(0);
  });

  it('hype multiplies positive vibe only — never softens a hit', () => {
    const { bus, state } = setup();
    bus.emit('meters:delta', { hype: 1 }); // hype -> 2
    bus.emit('meters:delta', { vibe: 10 });
    expect(state.vibe).toBe(70); // 50 + 10*2
    bus.emit('meters:delta', { vibe: -10 });
    expect(state.vibe).toBe(60); // full -10, unscaled
  });

  it('collects heat strikes and tracks clicker drift', () => {
    const { bus, state } = setup();
    bus.emit('heat:strike', { reason: 'minor admitted' });
    expect(state.heatStrikes).toHaveLength(1);
    bus.emit('door:clicker', { direction: 'in' });
    bus.emit('door:clicker', { direction: 'in' });
    bus.emit('door:clicker', { direction: 'out' });
    expect(state.capacity.clickerShown).toBe(1);
    bus.emit('door:clicker', { direction: 'out' });
    bus.emit('door:clicker', { direction: 'out' });
    expect(state.capacity.clickerShown).toBe(0); // clicker can't go negative
  });

  it('destroy() detaches all listeners', () => {
    const { bus, state, meters } = setup();
    meters.destroy();
    bus.emit('meters:delta', { vibe: 10 });
    expect(state.vibe).toBe(50);
  });
});
