import type { GameState, Inventory } from '@rpg/engine';
import { itemName } from './items';

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

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

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

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

export const QUESTS: QuestDef[] = [
    {
        id: 'bells',
        title: 'Три цветка',
        stages: [
            // Взятие: Ирвин рассказывает про поляны у прудов.
            {
                npc: 'elder',
                text: 'Слышать гул на закате — пепел дышит у прудов.',
                dialogue: 'elder_first',
                doneFlag: 'quest_bells_taken'
            },
            // Сбор: активная строка журнала с прогрессом; сдача — Ирвину.
            {
                npc: 'elder',
                text: 'Собрать лунные колокольчики у Серых прудов',
                progressKey: 'flowers',
                goal: QUEST_FLOWERS,
                dialogue: 'elder_hand_in',
                ready: (state) => state.getNumber('flowers') >= QUEST_FLOWERS,
                doneFlag: 'quest_bells_done',
                effect: 'plant_flowers'
            },
            // Эпилог: крючок акта 1 — разговор с Милой после посадки.
            {
                npc: 'trader',
                text: 'Цветы посажены у тропы. Поляна гудит.',
                dialogue: 'trader_after'
            }
        ]
    }
];

/** Квест взят: стоит doneFlag первой стадии. */
export function questTaken(state: GameState, quest: QuestDef): boolean {
    const first = quest.stages[0]!;
    return first.doneFlag !== undefined && state.hasFlag(first.doneFlag);
}

/** Квест завершён: все завершающие флаги стоят. */
export function questDone(state: GameState, quest: QuestDef): boolean {
    return quest.stages.every((s) => s.doneFlag === undefined || state.hasFlag(s.doneFlag));
}

/** Активная стадия: первая незавершённая (эпилог без 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 с готовым диалогом.
 * null — обычный repeat-диалог.
 */
export function questDialogueFor(state: GameState, npcId: string): string | null {
    for (const quest of QUESTS) {
        const stage = activeStage(state, quest);
        if (!stage || stage.npc !== npcId || !stage.dialogue) continue;
        if (stage.ready && !stage.ready(state)) continue;
        return stage.dialogue;
    }
    return null;
}

/** Побочные эффекты внеквестовых диалогов (знакомства). */
const EXTRA_EFFECTS: Record<string, string> = {
    trader_first: 'give_cloth' // Мила дарит полотно при знакомстве
};

/** Побочный эффект по завершённому диалогу (из стадий реестра и знакомств). */
export function questEffectFor(dialogueId: string): string | null {
    for (const quest of QUESTS) {
        for (const stage of quest.stages) {
            if (stage.dialogue === dialogueId && stage.effect) return stage.effect;
        }
    }
    return EXTRA_EFFECTS[dialogueId] ?? 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) => {
            // Эпилог (без doneFlag) достигнут — значит, завершён.
            const done = stage.doneFlag === undefined || state.hasFlag(stage.doneFlag);
            if (i > 0 && 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;
}

/** Строки сумки из инвентаря: имя + ×N (у одиночных — без множителя). */
export function inventoryItems(inventory: Inventory): string[] {
    const items = inventory.all.map((slot) =>
        slot.count > 1 ? `${itemName(slot.id)} ×${slot.count}` : itemName(slot.id)
    );
    if (items.length === 0) items.push('— пусто —');
    return items;
}