import { playSfx } from '../data/sfxSpecs';
import { MenuList, MenuSceneBase, Panel, PixelText } from '@rpg/engine';
import { Game } from '../Game';
import { areaOf } from '../data/locations';
import { SAVE_SLOTS, canDelete, slotTitle } from '../data/saves';
import type { SaveData } from './saveData';

/**
 * Меню сейвов: autosave (только загрузка) + 3 именованных слота
 * (загрузка/удаление). Панель поверх меню (push/pop). Подписи — из меты
 * слота; у старых сейвов без меты — полная загрузка (как раньше).
 */
export class SaveSlotsScene extends MenuSceneBase {
    constructor(
        private game: Game,
        private onPick: (save: SaveData) => void,
        private onBack: () => void
    ) {
        super(
            { input: game.engine.input, inputBlocked: () => game.scenes.transitioning },
            { up: 'up', down: 'down', confirm: 'advance', cancel: 'menu', extra: ['attack'] }
        );
    }

    protected build(): void {
        const panel = new Panel({ width: 240, height: 150 });
        panel.position.set((Game.VIRTUAL_W - 240) / 2, (Game.VIRTUAL_H - 150) / 2);

        const title = new PixelText({ text: 'СЕЙВЫ', size: 14, color: 0xd8c79a });
        title.anchor.set(0.5);
        title.position.set(120, 14);
        panel.addChild(title);

        this.menu = new MenuList({ width: 200, height: 14, gap: 3, size: 10 });
        this.menu.position.set(20, 36);
        panel.addChild(this.menu);

        this.view.addChild(panel);
        this.game.renderer.uiRoot.addChild(this.view);
        this.rebuild();
    }

    /** Delete на выбранном именованном слоте — стереть. */
    protected onAction(action: string, index: number): void {
        if (action === 'attack') this.deleteAt(index);
    }

    protected onCancel(): void {
        this.back();
    }

    /** Пересобрать список слотов из SaveManager. */
    private rebuild(): void {
        const items: { label: string; disabled?: boolean; onSelect?: () => void }[] = [];
        const slots = this.game.saves.listSlots();
        for (const slot of SAVE_SLOTS) {
            const meta = this.game.saves.slotMeta(slot);
            const save = meta
                ? null
                : slots.includes(slot)
                  ? this.game.saves.load<SaveData>(slot)!
                  : null;
            if (!meta && !save) {
                items.push({ label: `${slotTitle(slot)}  — пусто —`, disabled: true });
                continue;
            }
            const label = meta
                ? this.metaLabel(slot, meta)
                : this.saveLabel(slot, save!);
            items.push({
                label,
                onSelect: () => {
                    playSfx(this.game.audio, 'sfx/ui_click');
                    const picked = save ?? this.game.saves.load<SaveData>(slot)!;
                    this.onPick(picked);
                }
            });
        }
        items.push({ label: 'Назад', onSelect: () => this.back() });
        this.menu!.setItems(items);
    }

    /** Подпись из меты: локация из extras, время из savedAt. */
    private metaLabel(slot: string, meta: { savedAt?: number; extras?: Record<string, string | number | boolean> }): string {
        const area = typeof meta.extras?.area === 'string' ? meta.extras.area : undefined;
        const when = meta.savedAt ? this.formatTime(meta.savedAt) : '--:--';
        return `${slotTitle(slot)}  ${this.areaName(area)}  ${when}`;
    }

    /** Подпись из полного сейва (старые сейвы без меты). */
    private saveLabel(slot: string, save: SaveData): string {
        const areaId = save.area ?? (save as { location?: string }).location;
        return `${slotTitle(slot)}  ${this.areaName(areaId)}  ${this.formatTime(save.savedAt)}`;
    }

    private formatTime(ts: number): string {
        const date = new Date(ts);
        return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
    }

    private areaName(areaId: string | undefined): string {
        // Имя из реестра областей: интерьеры раньше показывались как «луга».
        return areaId ? areaOf(areaId).name : 'луга';
    }

    /** Удалить сейв в выбранной строке (именованные слоты; autosave защищён). */
    private deleteAt(index: number): void {
        const slot = SAVE_SLOTS[index];
        if (!slot || !canDelete(slot) || !this.game.saves.listSlots().includes(slot)) return;
        this.game.saves.delete(slot);
        playSfx(this.game.audio, 'sfx/ui_click');
        this.rebuild();
    }

    private back(): void {
        playSfx(this.game.audio, 'sfx/ui_click');
        this.onBack();
    }
}