import { evalConditions, type DialogueConditions, type DialogueWorld, type GameState } from '@rpg/engine';
import { FLAGS, VARS, type FlagId, type VarId } from './ids';

/**
 * Квестовая система (контент по docs/world.md).
 * Квест — декларативный набор стадий; состояние живёт во флагах/варах
 * GameState (ставятся графами диалогов), статус выводится из состояния.
 * Готовность стадии — те же условия, что и в графах диалогов (данные, не
 * замыкания — валидатор и dry-run их видят). Сцена спрашивает только
 * «какой диалог у NPC».
 */

/** Квест «Три цветка» (docs/world.md, акт 1): собрать и посадить колокольчики. */
export const QUEST_FLOWERS = 3;

/** Тайлы посадки поляны у тропы (Звенец): collectFlowers расползается от них. */
export const QUEST_PLANT_TILES: readonly (readonly [number, number])[] = [
    [15, 13],
    [16, 14],
    [15, 15]
];

/** Башня Звенца: тайл (камера кат-сцены сдачи идёт сюда). */
export const QUEST_TOWER_TILE = { x: 14, y: 7 };

/** Зелень у подножия башни: визуальный финал акта 1. */
export const QUEST_TOWER_GREEN: readonly (readonly [number, number])[] = [
    [13, 8],
    [15, 8],
    [14, 9]
];

/** Квест резонатора (акт 2): сколько тонов собрать у деревьев-механизмов. */
export const QUEST_TONES = 3;

/** WIRE-деревья рощи для звона (тайлы интерактивов tone_tree_1..3; достижимы от входа). */
export const QUEST_TONE_TILES: readonly (readonly [number, number])[] = [
    [16, 3],
    [6, 5],
    [10, 15]
];

/** Одна стадия квеста. */
export interface QuestStage {
    /** Чей диалог ведёт стадию (id из NpcDef). */
    npc: string;
    /** Строка журнала, пока стадия активна. */
    text: string;
    /** Прогресс N/M по var-ключу (если стадия считается в штуках). */
    progressKey?: VarId;
    goal?: number;
    /** Диалог стадии: взятие (первая) или сдача (промежуточная). */
    dialogue?: string;
    /** Готовность диалога — условия как в графах (по умолчанию сразу). */
    ready?: DialogueConditions;
    /** Флаг, которым граф диалога завершает стадию. Без него стадия — «эпилог». */
    doneFlag?: FlagId;
}

export interface QuestDef {
    id: string;
    title: string;
    /** Стадии по порядку; активная — первая незавершённая. */
    stages: QuestStage[];
}

export const QUESTS: QuestDef[] = [
    {
        id: 'bells',
        title: 'Три цветка',
        stages: [
            // Взятие: Ирвин рассказывает про поляны у прудов.
            {
                npc: 'elder',
                text: 'Пепел дышит у прудов. Поговорить с Ирвином',
                dialogue: 'elder_first',
                doneFlag: FLAGS.quest_bells_taken
            },
            // Сбор: активная строка журнала с прогрессом; сдача — Ирвину.
            {
                npc: 'elder',
                text: 'Собрать три колокольчика — Серые пруды, северо-запад лугов',
                progressKey: VARS.flowers,
                goal: QUEST_FLOWERS,
                dialogue: 'elder_hand_in',
                ready: { whenVars: [{ key: VARS.flowers, op: 'ge', value: QUEST_FLOWERS }] },
                doneFlag: FLAGS.quest_bells_done
            },
            // Эпилог: крючок акта 1 — разговор с Милой после посадки.
            {
                npc: 'trader',
                text: 'Поговорить с Милой — поляна у тропы гудит',
                dialogue: 'trader_after',
                doneFlag: FLAGS.act2_hook
            }
        ]
    },
    {
        // Акт 2: Клинт и его молчащий резонатор (docs/world.md, «Ржавая роща»).
        id: 'resonator',
        title: 'Голос для резонатора',
        stages: [
            // Взятие: ворчливое знакомство — тот же граф ставит met_clint.
            {
                npc: 'clint',
                text: 'Резонатор Клинта молчит. Поговорить с Клинтом',
                dialogue: 'clint_first',
                doneFlag: FLAGS.quest_resonator_taken
            },
            // Сбор тонов: деревья-механизмы рощи (интерактивы), сдача Клинту.
            {
                npc: 'clint',
                text: 'Прозвенеть у деревьев-механизмов — Ржавая роща, восток Звенца',
                progressKey: VARS.tones,
                goal: QUEST_TONES,
                dialogue: 'clint_tune',
                ready: { whenVars: [{ key: VARS.tones, op: 'ge', value: QUEST_TONES }] },
                doneFlag: FLAGS.quest_resonator_done
            },
            // Эпилог: подсказка о Машине — мост к финалу акта.
            {
                npc: 'clint',
                text: 'Зайти к Клинту — резонатор держит тон',
                dialogue: 'clint_repeat',
                doneFlag: FLAGS.machine_hook
            }
        ]
    }
];

/** Активная стадия: первая незавершённая (эпилог без doneFlag — тоже стадия). */
export function activeStage(state: GameState, quest: QuestDef): QuestStage | null {
    for (const stage of quest.stages) {
        if (stage.doneFlag !== undefined && state.hasFlag(stage.doneFlag)) continue;
        return stage;
    }
    return null;
}

/**
 * Диалог NPC по квест-стадиям: активная стадия этого NPC с готовым диалогом.
 * world — предикаты мира (сумка) для hasItem-условий. null — repeat-диалог.
 */
export function questDialogueFor(state: GameState, npcId: string, world?: DialogueWorld): string | null {
    for (const quest of QUESTS) {
        const stage = activeStage(state, quest);
        if (!stage || stage.npc !== npcId || !stage.dialogue) continue;
        if (stage.ready && !evalConditions(stage.ready, state, world)) continue;
        return stage.dialogue;
    }
    return null;
}

/** Одна строка журнала квестов. */
export interface QuestEntry {
    done: boolean;
    text: string;
}

/** Журнал: достигнутые стадии квестов. Взятия-стадия видна после принятия —
 *  журнал не «знает» о квесте раньше героя. */
export function questLog(state: GameState): QuestEntry[] {
    const entries: QuestEntry[] = [];
    for (const quest of QUESTS) {
        let reached = true;
        quest.stages.forEach((stage, i) => {
            const done = stage.doneFlag === undefined || state.hasFlag(stage.doneFlag);
            // Взятия-стадия (первая) видна, только когда принята (done);
            // остальные достигнутые стадии — всегда.
            const show = i > 0 || done;
            if (show && reached) {
                const progress =
                    stage.progressKey !== undefined && stage.goal !== undefined
                        ? ` (${Math.min(state.getNumber(stage.progressKey), stage.goal)}/${stage.goal})`
                        : '';
                entries.push({ done, text: `${stage.text}${progress}` });
            }
            if (!done) reached = false;
        });
    }
    return entries;
}

/** Трекер HUD: текст первой активной стадии с прогрессом (null — активных нет). */
export function questTracker(state: GameState): string | null {
    for (const quest of QUESTS) {
        const stage = activeStage(state, quest);
        if (!stage) continue;
        const progress =
            stage.progressKey !== undefined && stage.goal !== undefined
                ? ` (${Math.min(state.getNumber(stage.progressKey), stage.goal)}/${stage.goal})`
                : '';
        return `${stage.text}${progress}`;
    }
    return null;
}