import type { Encounter } from '@/lib/schemas';
import type { SystemId } from '@/lib/rules';
import { computeBudget } from '@/lib/combat/budget';
import type { Severity } from './advisors';
import type { CampaignContext } from './context';

export type ThemeKind = 'encounter-difficulty' | 'resource-attrition' | 'quest-stagnation';

export interface CampaignTheme {
  kind: ThemeKind;
  severity: Severity;
  tendency: string;
  evidence: string;
  recommendation?: string;
}

export type Skew = 'too-easy' | 'balanced' | 'too-hard';

/** difficulty label → 0 (trivial) … 4 (deadly/extreme), shared across systems. */
const ORDINAL: Record<string, number> = {
  trivial: 0, easy: 1, low: 1, medium: 2, moderate: 2, hard: 3, severe: 3, deadly: 4, extreme: 4,
};

function classify(ords: number[]): { skew: Skew; sampleSize: number; detail: string } {
  const n = ords.length;
  if (n < 3) return { skew: 'balanced', sampleSize: n, detail: `Only ${n} rated encounter${n === 1 ? '' : 's'} so far — not enough to spot a trend.` };
  const avg = ords.reduce((a, b) => a + b, 0) / n;
  const easyCount = ords.filter((o) => o <= 1).length;
  const hardCount = ords.filter((o) => o >= 3).length;
  if (avg < 1.5) {
    return { skew: 'too-easy', sampleSize: n, detail: `${easyCount} of the last ${n} encounters were easy or trivial for the party.` };
  }
  if (avg > 2.75) {
    return { skew: 'too-hard', sampleSize: n, detail: `${hardCount} of the last ${n} encounters were hard or deadly for the party.` };
  }
  return { skew: 'balanced', sampleSize: n, detail: `Encounter difficulty is well balanced across the last ${n} encounters.` };
}

/**
 * Classify whether the DM's recent encounters skew easy/hard for the party,
 * rating each fight against its party-level snapshot (or the fallback levels).
 */
export function difficultyTendency(
  encounters: Encounter[],
  system: SystemId,
  fallbackLevels: number[],
): { skew: Skew; sampleSize: number; detail: string } {
  const ords: number[] = [];
  for (const e of encounters) {
    if (e.status === 'planning') continue;
    const levels = e.partyLevelsSnapshot?.length ? e.partyLevelsSnapshot : fallbackLevels;
    const budget = computeBudget(system, levels, e.combatants);
    if (budget.monstersCounted > 0) ords.push(ORDINAL[budget.difficulty] ?? 2);
  }
  return classify(ords);
}

/** Deterministic campaign "themes" surfaced as insight cards and used to ground LLM tips. */
export function detectThemes(ctx: CampaignContext, window = 8): CampaignTheme[] {
  const themes: CampaignTheme[] = [];

  const rated = ctx.recentEncounters.slice(0, window).filter((e) => e.ratingXp > 0);
  const t = classify(rated.map((e) => ORDINAL[e.difficulty] ?? 2));
  if (t.skew === 'too-easy') {
    themes.push({
      kind: 'encounter-difficulty', severity: 'warn',
      tendency: 'Your encounters skew easy for the party.',
      evidence: t.detail,
      recommendation: 'Add a stronger creature or two to your next fight to raise the challenge.',
    });
  } else if (t.skew === 'too-hard') {
    themes.push({
      kind: 'encounter-difficulty', severity: 'warn',
      tendency: 'Your encounters skew hard for the party.',
      evidence: t.detail,
      recommendation: 'Consider easing the next encounter, or give the party a chance to rest first.',
    });
  }

  return themes;
}
