import { describe, it, expect } from 'vitest';
import { difficultyTendency, detectThemes } from './patterns';
import { buildCampaignContext } from './context';
import type { Campaign, Character, Encounter } from '@/lib/schemas';
import { characterDefaults } from '@/lib/schemas';

function enc(id: string, crs: number[], over: Partial<Encounter> = {}): Encounter {
  return {
    id, campaignId: 'c', name: id, status: 'ended', round: 1, turnIndex: 0,
    combatants: crs.map((cr, i) => ({
      id: `${id}-${i}`, name: 'Mob', kind: 'monster', initiative: 10, initBonus: 0, ac: 12,
      hp: { current: 5, max: 5, temp: 0 }, conditions: [], notes: '', cr,
    })),
    log: [], createdAt: `2026-01-0${id}`, updatedAt: '', ...over,
  };
}
function campaign(): Campaign {
  return { id: 'c', name: 'T', system: '5e', description: '', createdAt: '', updatedAt: '' };
}
function pc(level: number): Character {
  return {
    id: 'p', campaignId: 'c', system: '5e', kind: 'pc', name: 'P', ancestry: '', className: 'Fighter', level,
    abilities: { str: 10, dex: 10, con: 10, int: 10, wis: 10, cha: 10 },
    hp: { current: 10, max: 10, temp: 0 }, speed: 30, armorBonus: 0,
    skillRanks: {}, saveRanks: {}, perceptionRank: 'trained',
    ...characterDefaults(), notes: '', createdAt: '', updatedAt: '',
  };
}

describe('difficultyTendency', () => {
  it('flags a too-easy trend for a high-level party fighting weak mobs', () => {
    const fights = [enc('1', [0]), enc('2', [0.125]), enc('3', [0.25]), enc('4', [0])];
    const t = difficultyTendency(fights, '5e', [12, 12, 12, 12]);
    expect(t.skew).toBe('too-easy');
    expect(t.sampleSize).toBe(4);
  });
  it('flags a too-hard trend for a low-level party fighting strong mobs', () => {
    const fights = [enc('1', [8, 8]), enc('2', [9]), enc('3', [8, 8])];
    const t = difficultyTendency(fights, '5e', [1, 1, 1, 1]);
    expect(t.skew).toBe('too-hard');
  });
  it('returns balanced with low sample size', () => {
    const t = difficultyTendency([enc('1', [1])], '5e', [3, 3, 3, 3]);
    expect(t.skew).toBe('balanced');
    expect(t.sampleSize).toBe(1);
  });
  it('prefers the per-encounter snapshot over fallback levels', () => {
    // Snapshot says the party was level 1 when they fought CR-3 mobs → hard/deadly,
    // even though the fallback (current) levels are 20.
    const fights = [
      enc('1', [3, 3], { partyLevelsSnapshot: [1, 1, 1, 1] }),
      enc('2', [3, 3], { partyLevelsSnapshot: [1, 1, 1, 1] }),
      enc('3', [3], { partyLevelsSnapshot: [1, 1, 1, 1] }),
    ];
    const t = difficultyTendency(fights, '5e', [20, 20, 20, 20]);
    expect(t.skew).toBe('too-hard');
  });
});

describe('detectThemes', () => {
  it('produces an encounter-difficulty theme from a too-easy context', () => {
    const fights = [enc('1', [0]), enc('2', [0.125]), enc('3', [0.25]), enc('4', [0])];
    const ctx = buildCampaignContext({ campaign: campaign(), characters: [pc(12)], encounters: fights, quests: [], notes: [] });
    const themes = detectThemes(ctx);
    expect(themes.find((t) => t.kind === 'encounter-difficulty')?.tendency).toMatch(/easy/i);
    expect(themes[0]!.recommendation).toBeTruthy();
  });
});
