export type Primitive = string | number | boolean;
export type TimingTone = "best" | "good" | "neutral" | "risky";

export interface ValueDefinition {
  id: string;
  label: string;
  description?: string;
  min?: number;
  max?: number;
  initial?: number;
}

export interface StatDefinition extends ValueDefinition {}

export interface ResourceDefinition extends ValueDefinition {}

export interface InventoryDefinition extends ValueDefinition {}

export interface PhaseDefinition {
  id: string;
  label: string;
  description?: string;
}

export interface NumericComparator {
  eq?: number;
  neq?: number;
  gt?: number;
  gte?: number;
  lt?: number;
  lte?: number;
  oneOf?: number[];
}

export interface Condition {
  all?: Condition[];
  any?: Condition[];
  not?: Condition;
  phaseIn?: string[];
  actionIn?: string[];
  stat?: string;
  resource?: string;
  inventory?: string;
  flag?: string;
  tag?: string;
  age?: NumericComparator;
  day?: NumericComparator;
  turn?: NumericComparator;
  eq?: Primitive;
  neq?: Primitive;
  gt?: number;
  gte?: number;
  lt?: number;
  lte?: number;
  oneOf?: Primitive[];
}

export interface EffectPatch {
  stats?: Record<string, number>;
  resources?: Record<string, number>;
  inventory?: Record<string, number>;
  flags?: Record<string, boolean>;
  addTags?: string[];
  removeTags?: string[];
}

export interface TimingModifier {
  label: string;
  tone?: TimingTone;
  when?: Condition;
  effects?: EffectPatch;
}

export interface ActionDefinition {
  id: string;
  name: string;
  description: string;
  availability?: Condition;
  effects?: EffectPatch;
  advancePhases?: number;
  timing?: Record<string, TimingModifier>;
}

export interface EventDefinition {
  id: string;
  name: string;
  description: string;
  weight?: number;
  once?: boolean;
  when?: Condition;
  effects?: EffectPatch;
}

export interface StartDefinition {
  age?: number;
  day?: number;
  phaseId?: string;
  stats?: Record<string, number>;
  resources?: Record<string, number>;
  flags?: Record<string, boolean>;
  tags?: string[];
  inventory?: Record<string, number>;
}

export interface CalendarDefinition {
  daysPerAge?: number;
  maxDays?: number;
}

export interface WorldPresentation {
  label?: string;
  headline?: string;
  horizonLabel?: string;
}

export interface WorldDefinition {
  id: string;
  name: string;
  description: string;
  stats: StatDefinition[];
  resources?: ResourceDefinition[];
  inventory?: InventoryDefinition[];
  phases: PhaseDefinition[];
  actions: ActionDefinition[];
  events: EventDefinition[];
  start: StartDefinition;
  calendar?: CalendarDefinition;
  presentation?: WorldPresentation;
}

export interface PreparedWorldDefinition extends Omit<
  WorldDefinition,
  "resources" | "inventory"
> {
  resources: ResourceDefinition[];
  inventory: InventoryDefinition[];
}

export interface TimelineEntry {
  kind: "action" | "event";
  id: string;
  title: string;
  description: string;
  age: number;
  day: number;
  phaseId: string;
  phaseLabel: string;
  note?: string;
  tone?: TimingTone;
  changes: string[];
}

export interface GameState {
  worldId: string;
  originAge: number;
  age: number;
  day: number;
  turn: number;
  phaseIndex: number;
  phaseId: string;
  stats: Record<string, number>;
  resources: Record<string, number>;
  inventory: Record<string, number>;
  flags: Record<string, boolean>;
  tags: string[];
  seenEvents: Record<string, number>;
  log: TimelineEntry[];
}

export interface RuntimeContext {
  actionId?: string;
  phaseId?: string;
}

export interface AvailableAction extends ActionDefinition {
  isAvailable: boolean;
  isBestTiming: boolean;
  timingModifier?: TimingModifier;
}

export interface StepResult {
  state: GameState;
  action: TimelineEntry;
  event?: TimelineEntry;
  availableActions: AvailableAction[];
}
