import type { ItemId } from './items';

/**
 * Интерактивные объекты области: сундуки, очаги, записки, прилавки.
 * Первая подходящая реакция (по `when`) срабатывает; эффекты применяет
 * рантайм systems/Interactables.ts через sink сцены.
 */

/** Условие реакции: все указанные поля должны выполняться. */
export interface InteractWhen {
    /** Флаг поднят. */
    flag?: string;
    /** Флаг не поднят. */
    notFlag?: string;
    /** Вар не меньше значения. */
    varAtLeast?: { id: string; value: number };
}

/** Реакция объекта: текст (тост) + необязательные эффекты. */
export interface InteractResponse {
    /** Первая реакция с выполненным условием срабатывает (без when — всегда). */
    when?: InteractWhen;
    text: string;
    setFlags?: string[];
    clearFlags?: string[];
    setVar?: { id: string; value: number };
    /** Выдать предмет (в сумку). */
    gives?: ItemId;
    /** Сколько штук gives (по умолчанию 1). */
    count?: number;
    /** Ключ звука (sfx/...). */
    sound?: string;
}

/** Объект мира, с которым герой взаимодействует кликом. */
export interface InteractableDef {
    id: string;
    tile: { x: number; y: number };
    kind: 'examine' | 'pickup' | 'container' | 'lever' | 'signpost';
    /** Подпись при близости (и в снапшоте). */
    label?: string;
    /** Одноразовый: помечается флагом used:<id> и больше не реагирует. */
    once?: boolean;
    /** Без предмета — отказ с lockedText. */
    requiresItem?: ItemId;
    lockedText?: string;
    responses: InteractResponse[];
}

/** Что резолверу нужно знать о герое и мире (подставляется из GameState/сумки). */
export interface InteractCtx {
    hasFlag(flag: string): boolean;
    hasItem(id: ItemId): boolean;
    getVar(id: string): number;
    /** Одноразовый объект уже использован (флаг used:<id>). */
    used(id: string): boolean;
}

/** Результат взаимодействия: реакция / отказ (заперто) / ничего (пусто). */
export type InteractPick =
    | { ok: true; response: InteractResponse }
    | { ok: false; lockedText: string }
    | null;

/** Условие when выполнено (все указанные поля). */
function matches(when: InteractWhen | undefined, ctx: InteractCtx): boolean {
    if (!when) return true;
    if (when.flag !== undefined && !ctx.hasFlag(when.flag)) return false;
    if (when.notFlag !== undefined && ctx.hasFlag(when.notFlag)) return false;
    if (when.varAtLeast && ctx.getVar(when.varAtLeast.id) < when.varAtLeast.value) return false;
    return true;
}

/**
 * Чистый выбор реакции: первая подходящая по `when`; одноразовые объекты
 * после использования молчат (null); requiresItem без предмета — отказ.
 */
export function resolveInteractable(def: InteractableDef, ctx: InteractCtx): InteractPick {
    if (def.requiresItem && !ctx.hasItem(def.requiresItem)) {
        return { ok: false, lockedText: def.lockedText ?? 'Ничего не выйдет.' };
    }
    if (def.once && ctx.used(def.id)) return null;
    const response = def.responses.find((r) => matches(r.when, ctx));
    if (!response) return null;
    return { ok: true, response };
}

/** Контент интерьеров (см. docs/world.md: дом Ирвина, лавка Милы). */
export const INTERACTABLES: Record<'house_elder' | 'shop', InteractableDef[]> = {
    house_elder: [
        {
            id: 'chest_elder',
            tile: { x: 3, y: 3 },
            kind: 'container',
            label: 'Сундук',
            once: true,
            responses: [
                {
                    text: 'В сундуке — запас вощёного полотна.',
                    gives: 'cloth',
                    sound: 'sfx/ui_click'
                }
            ]
        },
        {
            id: 'hearth_elder',
            tile: { x: 8, y: 0 },
            kind: 'examine',
            label: 'Очаг',
            responses: [
                {
                    when: { flag: 'quest_bells_done' },
                    text: 'Очаг горит ровнее. Пепел отступает — и тепло возвращается.',
                    sound: 'sfx/bell_low'
                },
                { text: 'В очаге тлеют щепки. Тепло — редкость теперь.', sound: 'sfx/ash_hiss' }
            ]
        },
        {
            id: 'note_elder',
            tile: { x: 10, y: 4 },
            kind: 'examine',
            label: 'Записка',
            once: true,
            responses: [
                {
                    text: '«Тоны уходят вниз. Если колокол смолкнет — не буди Молчание».',
                    setFlags: ['read_note'],
                    sound: 'sfx/ui_click'
                }
            ]
        }
    ],
    shop: [
        {
            id: 'counter_shop',
            tile: { x: 5, y: 3 },
            kind: 'examine',
            label: 'Прилавок',
            responses: [
                {
                    when: { flag: 'quest_bells_done' },
                    text: 'На прилавке — соль и цветы в плошке. Поляна гудит — Мила звонит чаще.',
                    sound: 'sfx/bell_hit'
                },
                {
                    text: 'Соль, вощёное полотно, вода в бутлях. Цен Мила не пишет — звонит.',
                    sound: 'sfx/bell_hit'
                }
            ]
        }
    ]
};