import type { Camera } from '../render/Camera';
import type { EventBus } from '../core/EventBus';
import type { InputManager } from '../input/InputManager';
import type { SceneManager } from '../scene/SceneManager';

/**
 * Агентный мост (движковый каркас): машиночитаемый доступ к игре —
 * снапшоты состояния, детерминированные шаги, инъекция ввода, инварианты.
 * Игра строит контентный слой поверх каркаса (см. docs/engine/agent.md).
 * Всё, что делает мост, — никогда не бросает исключений: ошибка превращается
 * в слой снапшота `{ error: string }`, а не в потерю телеметрии.
 */

export type JsonValue = null | boolean | number | string | JsonValue[] | { [k: string]: JsonValue };
export type SnapshotLayer = { [k: string]: JsonValue };

/** Нарушенный инвариант: error — «мир сломан», warn — «подозрительно». */
export interface Invariant {
    /** Стабильный id: 'pos-nan', 'hero-in-wall', ... */
    id: string;
    severity: 'error' | 'warn';
    message: string;
    /** Где обнаружено: 'scene/LocationScene', 'engine/camera', ... */
    where?: string;
}

/**
 * Что сцена отдаёт мосту. Реализуется игровыми сценами; движок вызывает
 * методы через фабрику `() => SceneAgent | null` (сцена может быть не готова).
 */
export interface SceneAgent {
    /** Контентный слой снапшота этой сцены. */
    agentSnapshot(): SnapshotLayer;
    /** Инварианты сцены (мост мержит со своими и движковыми). */
    agentInvariants(): Invariant[];
    /** Произвольные команды (перемотки/читы для проверок). null — команда неизвестна. */
    agentCommand?(name: string, args?: JsonValue): JsonValue;
}

/** Минимальный хост, который нужен мосту (удовлетворяется Engine). */
export interface AgentHost {
    readonly scenes: SceneManager;
    readonly input: InputManager;
    readonly camera: Camera;
    readonly events: EventBus;
    /** Виртуальное разрешение (для пересчёта в CSS-пиксели в uiTap). */
    readonly virtualWidth: number;
    readonly virtualHeight: number;
    /** Один фиксированный шаг (без рендера); возвращает счётчик тиков. */
    stepTick(): number;
    /** Серия шагов в ручном режиме (setManual — без «догоняния» rAF). */
    stepTicks(n?: number, render?: boolean): number;
    renderFrame(): void;
    readonly tickCount: number;
    readonly fixedStep: number;
    /** Реальный FPS отрисовки (окно ~0,5 с). */
    readonly fps: number;
}

/** Движковый слой снапшота. */
export interface EngineSnapshot extends SnapshotLayer {
    tick: number;
    fps: number;
    fixedStep: number;
    scenes: string[];
    transitioning: boolean;
    camera: SnapshotLayer;
    pointer: SnapshotLayer;
}

export interface WaitForOptions {
    /** Лимит шагов (по умолчанию 600 — 10 с игрового времени). */
    timeoutTicks?: number;
    /** Рендерить ли каждый шаг (нужно только перед скриншотом). */
    render?: boolean;
}