/**
 * GdFinish — финишные ворота + конфетти при пересечении (этап G5).
 *
 * Ставит выбранную фабрику ворот на FINISH_X (из cylinder-примитива или из
 * самого правого ненулевого x уровня). Поворачивает поперёк трассы (Y=90°).
 *
 * При вызове .celebrate() запускает конфетти-партикль на 1.5с.
 *
 * Финиш-событие триггерится в скрипте уровня (по FINISH_X) — мы лишь рисуем
 * ворота. Подключим celebrate из BabylonScene при gdFinish сообщении.
 */
import {
    Vector3, TransformNode, ParticleSystem, Texture, DynamicTexture,
    Color3, Color4, MeshBuilder, StandardMaterial,
} from '@babylonjs/core';
import { FINISH_CATALOG } from '../../admin-preview/gdFinishes/finishFactories';

const DEFAULT_FINISH_BY_EPOCH = {
    1: 'f1_v4',   // Рустик (выбор юзера)
    2: 'f2_v5',   // Бронзовая
    3: 'f3_v3',
    4: 'f4_v4',
    5: 'f5_v2',
    6: 'f6_v4',
    7: 'f7_v1',
    8: 'f8_v5',
    9: 'f9_v4',
    10: 'f10_v5',
};

export class GdFinish {
    constructor() {
        this.scene = null;
        this._scene3d = null;
        this._handle = null;
        this._root = null;
        this._particles = null;
        this._particleEmitter = null;
        this._celebrated = false;
    }

    attach(scene, scene3d, epoch = 1, finishId = null) {
        if (!scene || !scene3d) return;
        this.scene = scene;
        this._scene3d = scene3d;
        const id = finishId || DEFAULT_FINISH_BY_EPOCH[epoch] || 'f1_v1';
        const factory = FINISH_CATALOG.find(f => f.id === id);
        if (!factory) {
            console.warn('[GdFinish] фабрика не найдена:', id);
            return;
        }
        // Определяем FINISH_X — ищем cylinder-примитив (это стандартный gd_finish)
        let finishX = null;
        const pm = scene3d.primitiveManager;
        if (pm) {
            for (const data of pm.instances.values()) {
                if (String(data.type) === 'cylinder' && typeof data.x === 'number' && data.x > 50) {
                    // самый правый cylinder = финиш
                    if (finishX == null || data.x > finishX) finishX = data.x;
                }
            }
        }
        if (finishX == null) {
            console.warn('[GdFinish] не нашли cylinder-финиш, ставлю на x=1000');
            finishX = 1000;
        }
        // Скрываем оригинальный cylinder если он рядом с финишем
        if (pm) {
            for (const data of pm.instances.values()) {
                if (String(data.type) === 'cylinder' && Math.abs(data.x - finishX) < 2 && data.mesh) {
                    try { data.mesh.setEnabled(false); } catch (e) {}
                    this._hiddenFinishCylinder = data.mesh;
                    break;
                }
            }
        }
        const h = factory.make(scene, `gd_finish_inst`);
        if (!h || !h.root) return;
        this._handle = h;
        this._root = h.root;
        this._root.position = new Vector3(finishX, 1, 0);
        this._root.rotation.y = Math.PI / 2;   // поперёк трассы
        this._finishX = finishX;
        this._setupConfetti(finishX);
        // Автоматически срабатывает когда куб игрока пересекает FINISH_X.
        // Скрипт уровня сам показывает win-screen, мы только конфетти добавим.
        this._onBeforeRender = () => {
            if (this._celebrated) return;
            const pp = this._scene3d?.player?._pos;
            if (!pp) return;
            if (pp.x >= this._finishX - 1.5) {
                this.celebrate();
            }
        };
        this.scene.onBeforeRenderObservable.add(this._onBeforeRender);
    }

    /** Создать ParticleSystem конфетти (старт по celebrate). */
    _setupConfetti(finishX) {
        // Маленький emitter-mesh — невидимая точка над финишем
        const emitter = MeshBuilder.CreateBox('gd_confetti_emitter', { size: 0.1 }, this.scene);
        emitter.position.set(finishX, 4, 0);
        emitter.isVisible = false;
        this._particleEmitter = emitter;

        // Текстура частицы — квадратик canvas (просто белый круг)
        const T = 32;
        const dt = new DynamicTexture('gd_confetti_tex', { width: T, height: T }, this.scene, true);
        const ctx = dt.getContext();
        ctx.clearRect(0, 0, T, T);
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.arc(T / 2, T / 2, T / 2 - 2, 0, Math.PI * 2);
        ctx.fill();
        dt.hasAlpha = true;
        dt.update();

        const ps = new ParticleSystem('gd_confetti', 400, this.scene);
        ps.particleTexture = dt;
        ps.emitter = emitter;
        ps.minEmitBox = new Vector3(-1.5, 0, -1.5);
        ps.maxEmitBox = new Vector3(1.5, 0, 1.5);
        // Конфетти разных цветов
        ps.color1 = new Color4(1, 0.3, 0.4, 1);
        ps.color2 = new Color4(0.3, 0.7, 1, 1);
        ps.colorDead = new Color4(1, 1, 1, 0);
        ps.minSize = 0.15; ps.maxSize = 0.35;
        ps.minLifeTime = 1.0; ps.maxLifeTime = 2.5;
        ps.emitRate = 0;   // пока выключен
        ps.gravity = new Vector3(0, -8, 0);
        ps.direction1 = new Vector3(-3, 5, -3);
        ps.direction2 = new Vector3(3, 8, 3);
        ps.minAngularSpeed = -3; ps.maxAngularSpeed = 3;
        ps.minEmitPower = 1; ps.maxEmitPower = 3;
        ps.updateSpeed = 0.02;
        ps.start();   // активен но без эмиссии
        this._particles = ps;
    }

    /** Включить конфетти на ~1.5 секунды. Вызывает уровень при пересечении финиша. */
    celebrate() {
        if (this._celebrated || !this._particles) return;
        this._celebrated = true;
        this._particles.emitRate = 250;
        setTimeout(() => {
            try { this._particles.emitRate = 0; } catch (e) {}
        }, 1500);
    }

    dispose() {
        try {
            if (this._onBeforeRender && this.scene) {
                this.scene.onBeforeRenderObservable.removeCallback(this._onBeforeRender);
                this._onBeforeRender = null;
            }
        } catch (e) {}
        if (this._handle && this._handle.dispose) try { this._handle.dispose(); } catch (e) {}
        if (this._particles) try { this._particles.dispose(); } catch (e) {}
        if (this._particleEmitter) try { this._particleEmitter.dispose(); } catch (e) {}
        if (this._hiddenFinishCylinder) try { this._hiddenFinishCylinder.setEnabled(true); } catch (e) {}
        this._handle = null;
        this._root = null;
        this._particles = null;
        this._particleEmitter = null;
        this._hiddenFinishCylinder = null;
        this.scene = null;
        this._scene3d = null;
    }
}
