/**
 * T010d — "Relationship at risk" neglect nudge.
 *
 * Fires only for an NPC the player once felt strongly about (affinityWasHigh)
 * whose affinity has since decayed past the at-risk threshold and who has not
 * already been nudged for this decline. No real APNs needed.
 */
import { describe, it, expect, beforeEach } from 'vitest';
import { Person } from '../../../src/models/Person.js';
import { Player } from '../../../src/models/Player.js';
import {
  shouldNudgeAtRisk,
  checkRelationshipAtRiskNudges,
  RELATIONSHIP_AT_RISK_AFFINITY,
} from '../../../src/events/conversations/npc_initiative.js';

function makePerson(opts: { affinity: number; wasHigh?: boolean; notified?: boolean; status?: 'alive' | 'dead' }): Person {
  return new Person({
    id: `npc-${Math.random().toString(36).slice(2)}`,
    firstname: 'Jamie',
    lastname: 'R',
    sex: 'Female',
    ageYears: 30,
    affinity: opts.affinity,
    affinityWasHigh: opts.wasHigh,
    neglectAtRiskNotified: opts.notified,
    status: opts.status ?? 'alive',
    relationships: ['friend'],
  } as never);
}

function makePlayer(r: Person[]): Player {
  return new Player({
    userId: 'p1',
    character: new Person({ id: 'me', firstname: 'A', lastname: 'B', sex: 'Male', ageYears: 30 } as never),
    status: 'playing',
    controller: 'active',
    r,
    date: '01-01',
  });
}

describe('shouldNudgeAtRisk', () => {
  it('fires for a once-high NPC that decayed past the threshold', () => {
    const npc = makePerson({ affinity: RELATIONSHIP_AT_RISK_AFFINITY - 5, wasHigh: true });
    expect(shouldNudgeAtRisk(npc)).toBe(true);
  });

  it('does NOT fire for an NPC that was never high', () => {
    const npc = makePerson({ affinity: RELATIONSHIP_AT_RISK_AFFINITY - 5, wasHigh: false });
    expect(shouldNudgeAtRisk(npc)).toBe(false);
  });

  it('does NOT fire while affinity is still above the threshold', () => {
    const npc = makePerson({ affinity: RELATIONSHIP_AT_RISK_AFFINITY + 20, wasHigh: true });
    expect(shouldNudgeAtRisk(npc)).toBe(false);
  });

  it('does NOT fire twice (already notified)', () => {
    const npc = makePerson({ affinity: RELATIONSHIP_AT_RISK_AFFINITY - 5, wasHigh: true, notified: true });
    expect(shouldNudgeAtRisk(npc)).toBe(false);
  });

  it('does NOT fire for a dead NPC', () => {
    const npc = makePerson({ affinity: RELATIONSHIP_AT_RISK_AFFINITY - 5, wasHigh: true, status: 'dead' });
    expect(shouldNudgeAtRisk(npc)).toBe(false);
  });
});

describe('checkRelationshipAtRiskNudges', () => {
  let qualifying: Person;

  beforeEach(() => {
    qualifying = makePerson({ affinity: RELATIONSHIP_AT_RISK_AFFINITY - 10, wasHigh: true });
  });

  it('nudges only qualifying NPCs and marks them notified', async () => {
    const stillHigh = makePerson({ affinity: 80, wasHigh: true });
    const neverHigh = makePerson({ affinity: 10, wasHigh: false });
    const player = makePlayer([qualifying, stillHigh, neverHigh]);

    const nudged = await checkRelationshipAtRiskNudges(player);

    expect(nudged).toEqual([qualifying.id]);
    expect(qualifying.neglectAtRiskNotified).toBe(true);
    expect(stillHigh.neglectAtRiskNotified).toBeFalsy();
  });

  it('does not re-nudge an already-notified NPC on a later check', async () => {
    const player = makePlayer([qualifying]);

    const first = await checkRelationshipAtRiskNudges(player);
    expect(first).toEqual([qualifying.id]);

    const second = await checkRelationshipAtRiskNudges(player);
    expect(second).toEqual([]);
  });
});
