import { describe, it, expect, beforeEach } from 'vitest';
import { db } from './db';
import { campaignsRepo, charactersRepo, encountersRepo, diceRepo, notesRepo, npcsRepo, questsRepo, calendarRepo, homebrewRepo } from './repositories';

beforeEach(async () => {
  await db.delete();
  await db.open();
});

describe('campaign cascade delete', () => {
  it('removes all child entities atomically (old app orphaned them forever)', async () => {
    const a = await campaignsRepo.create({ name: 'Curse of Strahd', system: '5e', description: '' });
    const b = await campaignsRepo.create({ name: 'Other', system: 'pf2e', description: '' });

    await charactersRepo.create(a.id, {
      system: '5e', name: 'Ezmerelda', kind: 'pc', ancestry: 'Human', className: 'Ranger', level: 5,
    });
    await encountersRepo.create(a.id, 'Death House');
    await diceRepo.add({ campaignId: a.id, label: 'attack', expression: '1d20', total: 14, breakdown: '' });
    await notesRepo.create(a.id, 'Barovia');
    await npcsRepo.create(a.id, 'Strahd');
    await questsRepo.create(a.id, 'Escape the mists');
    await calendarRepo.save({ campaignId: a.id, currentDay: 3, events: [] });
    await homebrewRepo.create(a.id, '5e', 'monster', 'Strahd Zombie');

    // unrelated campaign's data must survive
    await charactersRepo.create(b.id, {
      system: 'pf2e', name: 'Keep me', kind: 'pc', ancestry: 'Elf', className: 'Wizard', level: 1,
    });

    await campaignsRepo.remove(a.id);

    expect(await campaignsRepo.get(a.id)).toBeUndefined();
    expect(await charactersRepo.listByCampaign(a.id)).toHaveLength(0);
    expect(await encountersRepo.listByCampaign(a.id)).toHaveLength(0);
    expect(await diceRepo.recent(a.id)).toHaveLength(0);
    expect(await notesRepo.listByCampaign(a.id)).toHaveLength(0);
    expect(await npcsRepo.listByCampaign(a.id)).toHaveLength(0);
    expect(await questsRepo.listByCampaign(a.id)).toHaveLength(0);
    expect(await homebrewRepo.listByCampaign(a.id)).toHaveLength(0);
    expect(await db.calendars.get(a.id)).toBeUndefined();

    expect(await charactersRepo.listByCampaign(b.id)).toHaveLength(1);
  });
});

describe('validation on write', () => {
  it('rejects NaN HP', async () => {
    const c = await campaignsRepo.create({ name: 'C', system: '5e', description: '' });
    const enc = await encountersRepo.create(c.id, 'E');
    enc.combatants.push({
      id: 'x', name: 'Goblin', kind: 'monster', initiative: 12, initBonus: 0, ac: 15,
      hp: { current: Number.NaN, max: 7, temp: 0 }, conditions: [], notes: '',
    });
    await expect(encountersRepo.save(enc)).rejects.toThrow();
  });
});
