/**
 * Tests for the end-of-life summary + score built by handleDeath.
 *
 * Covers:
 *  - lifeSummary is populated with the expected fields on death
 *  - score is positive for a rich life
 *  - the score formula is monotonic: richer / longer / more-accomplished lives
 *    score strictly higher
 */
import { describe, it, expect, beforeEach } from 'vitest';
import { Person } from '../../../src/models/Person.js';
import { Player } from '../../../src/models/Player.js';
import {
  handleDeath,
  buildLifeSummary,
  computeLifeScore,
  type LifeSummary,
} from '../../../src/services/health/health_manager.js';
import { clearAllStatistics } from '../../../src/services/retention/statistics.js';

function makeCashierJob() {
  return {
    title: 'Cashier',
    levels: [
      { title: 'Junior Cashier', salary: 550 },
      { title: 'Cashier', salary: 700 },
      { title: 'Store Manager', salary: 1150 },
    ],
  };
}

function makeRichLife(): Player {
  const character = new Person({
    id: 'me',
    firstname: 'Rich',
    lastname: 'Life',
    sex: 'Male',
    status: 'alive',
    ageYears: 88,
    money: 250000,
    salary: 1150,
    children: [
      { id: 'k1', firstname: 'A', ageDays: 0, ageYears: 5, sex: 'Female' },
      { id: 'k2', firstname: 'B', ageDays: 0, ageYears: 8, sex: 'Male' },
    ],
  } as never);
  (character as unknown as { job?: unknown }).job = makeCashierJob();

  const player = new Player({
    userId: 'rich-user',
    character,
    status: 'playing',
    controller: 'active',
    r: [
      new Person({ id: 'r1', firstname: 'Spouse', lastname: 'X' } as never),
      new Person({ id: 'r2', firstname: 'Friend', lastname: 'Y' } as never),
      new Person({ id: 'r3', firstname: 'Coworker', lastname: 'Z' } as never),
    ],
  });
  player.messageLog = [
    'You graduated from high school.',
    'You got married!',
    'Your child was born.',
    'You were promoted to Store Manager.',
    'Just an ordinary Tuesday.',
  ];
  return player;
}

function makePoorLife(): Player {
  const character = new Person({
    id: 'me2',
    firstname: 'Poor',
    lastname: 'Life',
    sex: 'Female',
    status: 'alive',
    ageYears: 19,
    money: 0,
    children: [],
  } as never);

  return new Player({
    userId: 'poor-user',
    character,
    status: 'playing',
    controller: 'active',
    r: [],
  });
}

describe('life summary', () => {
  beforeEach(() => {
    clearAllStatistics();
  });

  it('populates lifeSummary with the expected fields on death', () => {
    const player = makeRichLife();

    handleDeath(player);

    const summary = player.lifeSummary as LifeSummary;
    expect(summary).toBeTruthy();
    expect(summary.finalAge).toBe(88);
    expect(summary.netWorth).toBe(250000);
    expect(summary.peakCareer).toEqual({ title: 'Cashier', bestIncome: 1150 });
    expect(summary.relationshipsCount).toBe(3);
    expect(summary.childrenCount).toBe(2);
    expect(Array.isArray(summary.notableEvents)).toBe(true);
    // Notable events pull highlights, not the ordinary line.
    expect(summary.notableEvents).toContain('You got married!');
    expect(summary.notableEvents).not.toContain('Just an ordinary Tuesday.');
    expect(typeof summary.achievementsEarned).toBe('number');
    expect(typeof summary.diedAt).toBe('string');
    expect(summary.score).toBeGreaterThan(0);
  });

  it('produces a positive score for a rich life', () => {
    const player = makeRichLife();
    const summary = buildLifeSummary(player);
    expect(summary.score).toBeGreaterThan(0);
  });

  it('a richer/longer/more-accomplished life scores higher (monotonic)', () => {
    const rich = buildLifeSummary(makeRichLife());
    const poor = buildLifeSummary(makePoorLife());
    expect(rich.score).toBeGreaterThan(poor.score);
  });

  it('score increases monotonically in each weighted dimension', () => {
    const base = {
      finalAge: 50,
      netWorth: 10000,
      lifetimeEarnings: 50000,
      peakCareer: { title: 'Cashier', bestIncome: 700 },
      relationshipsCount: 2,
      childrenCount: 1,
      achievementsEarned: 3,
    } as const;
    const baseScore = computeLifeScore(base);

    expect(computeLifeScore({ ...base, finalAge: 80 })).toBeGreaterThan(baseScore);
    expect(computeLifeScore({ ...base, netWorth: 1_000_000 })).toBeGreaterThan(baseScore);
    expect(computeLifeScore({ ...base, lifetimeEarnings: 5_000_000 })).toBeGreaterThan(baseScore);
    expect(
      computeLifeScore({ ...base, peakCareer: { title: 'Cashier', bestIncome: 5000 } })
    ).toBeGreaterThan(baseScore);
    expect(computeLifeScore({ ...base, relationshipsCount: 10 })).toBeGreaterThan(baseScore);
    expect(computeLifeScore({ ...base, childrenCount: 5 })).toBeGreaterThan(baseScore);
    expect(computeLifeScore({ ...base, achievementsEarned: 20 })).toBeGreaterThan(baseScore);
  });

  it('clamps negative inputs so score never goes below the longevity floor', () => {
    const summary = computeLifeScore({
      finalAge: 0,
      netWorth: -5000,
      lifetimeEarnings: -1000,
      peakCareer: null,
      relationshipsCount: 0,
      childrenCount: 0,
      achievementsEarned: 0,
    });
    expect(summary).toBe(0);
  });
});
