import { describe, expect, it } from 'vitest';
import type { Vec2 } from '@rpg/engine';
import { resolveClick, type ClickProbe } from '../ClickRouting';
import type { NpcDef } from '../../data/npcs';
import type { InteractableDef } from '../../data/interactables';
import type { TransitionDef } from '../../data/locations';

const npc: NpcDef = {
    id: 'elder',
    name: 'Ирвин',
    sprite: 'elder',
    pos: { x: 5.5, y: 5.5 },
    tile: { x: 5, y: 5 },
    flagKey: 'met_elder',
    dialogueFirst: 'd1',
    dialogueRepeat: 'd2'
};

const chest: InteractableDef = {
    id: 'chest',
    kind: 'container',
    pos: { x: 6.5, y: 5.5 },
    tile: { x: 6, y: 5 },
    responses: []
};

const well: TransitionDef = {
    tile: { x: 7, y: 5 },
    label: 'колодец',
    target: { kind: 'area', area: 'meadows', entry: { x: 1, y: 1 } }
};

/** Проба клика: тайл и мир задаются тестом, остальное — заглушки. */
function probe(opts: {
    clicked?: { x: number; y: number } | null;
    world?: Vec2;
    npcAt?: ClickProbe['npcAt'];
    transitionPick?: ClickProbe['transitionPick'];
    interactableAt?: ClickProbe['interactableAt'];
    flowerAt?: ClickProbe['flowerAt'];
    enemyAt?: ClickProbe['enemyAt'];
}): ClickProbe {
    return {
        world: opts.world ?? { x: 0, y: 0 },
        clicked: opts.clicked ?? null,
        npcAt: opts.npcAt ?? (() => null),
        transitionPick: opts.transitionPick ?? null,
        interactableAt: opts.interactableAt ?? (() => null),
        flowerAt: opts.flowerAt ?? (() => false),
        enemyAt: opts.enemyAt ?? (() => null)
    };
}

describe('resolveClick — приоритеты клика по миру', () => {
    it('NPC на тайле — talk (выше перехода и интерактива)', () => {
        const a = resolveClick(
            probe({
                clicked: { x: 5, y: 5 },
                npcAt: () => npc,
                transitionPick: { ok: true, def: well },
                interactableAt: () => chest
            })
        );
        expect(a).toEqual({ kind: 'talk', def: npc });
    });

    it('клик-переход: открытый — transition', () => {
        const a = resolveClick(probe({ clicked: { x: 7, y: 5 }, transitionPick: { ok: true, def: well } }));
        expect(a).toEqual({ kind: 'transition', def: well });
    });

    it('клик-переход: запертый — locked с текстом (не движение)', () => {
        const a = resolveClick(
            probe({
                clicked: { x: 7, y: 5 },
                transitionPick: { ok: false, lockedText: 'Заперто.' }
            })
        );
        expect(a).toEqual({ kind: 'locked', text: 'Заперто.' });
    });

    it('интерактивный объект на тайле — interact', () => {
        const a = resolveClick(probe({ clicked: { x: 6, y: 5 }, interactableAt: () => chest }));
        expect(a).toEqual({ kind: 'interact', def: chest });
    });

    it('сборный тайл (цветок) — flower', () => {
        const a = resolveClick(
            probe({ clicked: { x: 3, y: 3 }, flowerAt: (x, y) => x === 3 && y === 3 })
        );
        expect(a).toEqual({ kind: 'flower', x: 3, y: 3 });
    });

    it('враг под точкой мира — enemy (тайл может быть за картой)', () => {
        const e = { id: 1 } as never;
        const a = resolveClick(
            probe({ clicked: null, world: { x: 10, y: 20 }, enemyAt: (w) => (w.x === 10 ? e : null) })
        );
        expect(a).toEqual({ kind: 'enemy', entity: e });
    });

    it('клик за картой без врага — move', () => {
        expect(resolveClick(probe({ clicked: null }))).toEqual({ kind: 'move' });
        expect(resolveClick(probe({ clicked: { x: 9, y: 9 } }))).toEqual({ kind: 'move' });
    });
});