import { describe, it, expect } from 'vitest';
import {
  STAT_BOUNDS,
  clampAllStats,
  clampPlayerStats,
  setStat,
  modifyStat,
} from '../../src/utils/statUtils.js';
import type { Person } from '../../src/models/Person.js';
import type { Player } from '../../src/models/Player.js';

/**
 * Fix 0-B regression: affinity is a relationship stat that ranges -100..100.
 * The old bound of {min:0,max:100} wiped negative relationships during the
 * nightly clampPlayerStats pass. Negative affinity must now survive clamping.
 */
describe('STAT_BOUNDS.affinity range (Fix 0-B)', () => {
  it('uses the -100..100 range with a default of 50', () => {
    expect(STAT_BOUNDS.affinity.min).toBe(-100);
    expect(STAT_BOUNDS.affinity.max).toBe(100);
    expect(STAT_BOUNDS.affinity.default).toBe(50);
  });

  it('setStat does not floor negative affinity at 0', () => {
    expect(setStat(-40, 'affinity')).toBe(-40);
    expect(setStat(-200, 'affinity')).toBe(-100);
    expect(setStat(200, 'affinity')).toBe(100);
  });

  it('modifyStat allows affinity to go negative', () => {
    expect(modifyStat(20, -60, 'affinity')).toBe(-40);
    expect(modifyStat(-90, -50, 'affinity')).toBe(-100);
  });

  it('clampAllStats preserves a negative affinity (-40)', () => {
    const person = { affinity: -40, energy: 50 } as unknown as Person;
    clampAllStats(person);
    expect(person.affinity).toBe(-40);
  });

  it('clampAllStats still floors affinity below -100', () => {
    const person = { affinity: -250 } as unknown as Person;
    clampAllStats(person);
    expect(person.affinity).toBe(-100);
  });

  it('clampPlayerStats preserves negative affinity across player.r relationships', () => {
    const player = {
      c: { affinity: 50, energy: 80 },
      r: [
        { affinity: -40 },
        { affinity: -100 },
        { affinity: -300 },
        { affinity: 75 },
      ],
    } as unknown as Player;

    clampPlayerStats(player);

    expect(player.r![0].affinity).toBe(-40);
    expect(player.r![1].affinity).toBe(-100);
    expect(player.r![2].affinity).toBe(-100); // floored, not zeroed
    expect(player.r![3].affinity).toBe(75);
  });
});
