/**
 * Family & Legacy keystone regression tests.
 *
 * Before this fix, a pregnancy granted a `child_born` achievement at conception
 * but NO child Person was ever created — so inheritance/heir/legacy and all
 * `child`-gated parenting content were permanently dead. These tests lock in the
 * keystone behavior: a pregnancy that reaches term creates a real child Person
 * with a `child` relationship and credits `child_born` AT birth.
 */
import { describe, it, expect } from 'vitest';
import { PlayerFactory } from '../../src/testing/PlayerFactory.js';
import { checkPregnancyTerm } from '../../src/services/character/character_manager.js';

function childrenOf(player: any) {
  return (player.r ?? []).filter((p: any) => (p.relationships ?? []).includes('child'));
}

describe('Family & Legacy keystone: pregnancy creates a real child', () => {
  it('does nothing while not pregnant', () => {
    const player: any = PlayerFactory.createAtAge(30);
    const before = childrenOf(player).length;
    const msg = checkPregnancyTerm(player);
    expect(msg).toBeNull();
    expect(childrenOf(player).length).toBe(before);
  });

  it('does not deliver before term', () => {
    const player: any = PlayerFactory.createAtAge(30);
    player.c.pregnant = true;
    player.c.pregnancyDueDay = (player.c.ageDays ?? 0) + 252;
    const msg = checkPregnancyTerm(player);
    expect(msg).toBeNull();
    expect(childrenOf(player).length).toBe(0);
    expect(player.c.pregnant).toBe(true); // still cooking
  });

  it('delivers a real child at term and credits child_born once', () => {
    const player: any = PlayerFactory.createAtAge(30);
    player.lifecycleQueue = [];
    const startKids = childrenOf(player).length;

    // Conceive, then jump to term.
    player.c.pregnant = true;
    player.c.pregnancyDueDay = (player.c.ageDays ?? 0); // due now

    const msg = checkPregnancyTerm(player);

    // A real child Person now exists with the 'child' relationship.
    const kids = childrenOf(player);
    expect(kids.length).toBe(startKids + 1);
    const child = kids[0];
    expect(child.relationships).toContain('child');
    expect(child.relationships).toContain('family');
    expect(child.ageYears).toBe(0);
    expect(child.lastname).toBe(player.c.lastname);

    // child_born credit queued AT birth (for both loops' lifecycle drain).
    expect(player.lifecycleQueue.some((e: any) => e.type === 'child_born')).toBe(true);

    // Birth message surfaced to the player.
    expect(msg).toBeTruthy();
    expect((player.messageQueue ?? []).some((m: string) => /born/i.test(m))).toBe(true);

    // Pregnancy state cleared.
    expect(player.c.pregnant).toBeFalsy();
    expect(player.c.pregnancyDueDay).toBeUndefined();

    // Fires exactly once: a second daily check delivers nothing more.
    const before = childrenOf(player).length;
    const msg2 = checkPregnancyTerm(player);
    expect(msg2).toBeNull();
    expect(childrenOf(player).length).toBe(before);
  });

  it('legacy save with no due day gets a term rather than hanging forever', () => {
    const player: any = PlayerFactory.createAtAge(30);
    player.c.pregnant = true;
    player.c.pregnancyDueDay = undefined; // simulate a pre-fix save
    const msg = checkPregnancyTerm(player);
    expect(msg).toBeNull();
    expect(typeof player.c.pregnancyDueDay).toBe('number'); // term assigned
  });
});
