/**
 * GdPlayerTrail — частицы-шлейф за кубом игрока (этап G8).
 *
 * 3 типа trail соответствуют скинам из магазина (cubeSkinFactories.CUBE_TRAILS):
 *   - trail_white — белые точки, мягкое мерцание
 *   - trail_fire — оранжево-жёлтые искры с гравитацией
 *   - trail_ice — синие звёздочки, медленно падают
 *
 * Тип берётся из gd_progress.equipped_trail. При смене trail в магазине
 * нужно пересоздать (мы пересоздаём при следующем enterPlayMode).
 */
import {
    ParticleSystem, Color4, Color3, Vector3, MeshBuilder, StandardMaterial,
    DynamicTexture, Texture,
} from '@babylonjs/core';

const PLAYER_PRIM_ID = 10001;
const STORYS_BASE = '/api-storys';

export class GdPlayerTrail {
    constructor() {
        this.scene = null;
        this._scene3d = null;
        this._cubeMesh = null;
        this._emitter = null;
        this._particles = null;
        this._textureRefs = [];
    }

    /** projectId нужен чтобы прочитать gd_progress.equipped_trail. */
    async attach(scene, scene3d, projectId, userId) {
        if (!scene || !scene3d) return;
        this.scene = scene;
        this._scene3d = scene3d;
        // Прочитать выбранный trail
        let trailId = 'trail_white';
        try {
            const url = `${STORYS_BASE}/kubikon3d/savegame/${projectId}/${userId}/gd_progress`;
            const r = await fetch(url, {
                headers: { Authorization: localStorage.getItem('Authorization') || '' },
            });
            if (r.ok) {
                const j = await r.json();
                trailId = j?.data?.equipped_trail || 'trail_white';
            }
        } catch (e) { /* fallback на trail_white */ }
        // Ждём куб игрока (он создаётся в primitiveManager при load)
        let attempts = 0;
        const tryAttach = () => {
            attempts++;
            const pm = scene3d.primitiveManager;
            const data = pm?.instances?.get(PLAYER_PRIM_ID);
            const mesh = data?.mesh;
            if (!mesh) {
                if (attempts < 10) setTimeout(tryAttach, 200);
                return;
            }
            this._cubeMesh = mesh;
            this._setupTrail(trailId);
            console.log(`[GdPlayerTrail] trail=${trailId}, attached`);
        };
        tryAttach();
    }

    _setupTrail(trailId) {
        const ps = new ParticleSystem('gd_trail', 200, this.scene);
        ps.particleTexture = this._makeTexture(trailId);
        ps.emitter = this._cubeMesh;   // emitter — сам куб, частицы рождаются вокруг него
        ps.minEmitBox = new Vector3(-0.3, -0.3, -0.3);
        ps.maxEmitBox = new Vector3(0.3, 0.3, 0.3);
        ps.minSize = 0.15;
        ps.maxSize = 0.35;
        ps.minLifeTime = 0.25;
        ps.maxLifeTime = 0.6;
        ps.emitRate = 60;
        ps.minAngularSpeed = -2;
        ps.maxAngularSpeed = 2;
        ps.updateSpeed = 0.02;

        if (trailId === 'trail_fire') {
            ps.color1 = new Color4(1.0, 0.7, 0.1, 1);
            ps.color2 = new Color4(1.0, 0.3, 0.0, 1);
            ps.colorDead = new Color4(0.2, 0.0, 0.0, 0);
            ps.minSize = 0.20; ps.maxSize = 0.45;
            ps.minLifeTime = 0.30; ps.maxLifeTime = 0.7;
            ps.gravity = new Vector3(0, -3, 0);
            ps.direction1 = new Vector3(-1, -1, -1);
            ps.direction2 = new Vector3(1, 0, 1);
            ps.blendMode = ParticleSystem.BLENDMODE_ADD;
            ps.emitRate = 80;
        } else if (trailId === 'trail_ice') {
            ps.color1 = new Color4(0.55, 0.85, 1.0, 1);
            ps.color2 = new Color4(0.85, 0.95, 1.0, 1);
            ps.colorDead = new Color4(0.7, 0.85, 1.0, 0);
            ps.minSize = 0.18; ps.maxSize = 0.35;
            ps.gravity = new Vector3(0, -2, 0);
            ps.direction1 = new Vector3(-0.5, -0.5, -0.5);
            ps.direction2 = new Vector3(0.5, 0.2, 0.5);
            ps.blendMode = ParticleSystem.BLENDMODE_STANDARD;
        } else {
            // trail_white — мягкие белые точки
            ps.color1 = new Color4(1, 1, 1, 0.95);
            ps.color2 = new Color4(0.95, 0.95, 1.0, 0.85);
            ps.colorDead = new Color4(1, 1, 1, 0);
            ps.gravity = new Vector3(0, 0, 0);
            ps.direction1 = new Vector3(-0.3, -0.3, -0.3);
            ps.direction2 = new Vector3(0.3, 0.3, 0.3);
            ps.blendMode = ParticleSystem.BLENDMODE_STANDARD;
        }
        ps.minEmitPower = 0.3;
        ps.maxEmitPower = 1.0;
        ps.start();
        this._particles = ps;
    }

    /** Текстура частицы — круг с белым/цветным мягким градиентом. */
    _makeTexture(trailId) {
        const S = 64;
        const dt = new DynamicTexture(`gd_trail_${trailId}_tex`, { width: S, height: S }, this.scene, true);
        const ctx = dt.getContext();
        ctx.clearRect(0, 0, S, S);
        const cx = S / 2, cy = S / 2;
        const g = ctx.createRadialGradient(cx, cy, 0, cx, cy, S / 2);
        if (trailId === 'trail_ice') {
            // Снежинка-звёздочка
            ctx.strokeStyle = '#cce4ff';
            ctx.lineWidth = 3;
            ctx.lineCap = 'round';
            for (let i = 0; i < 6; i++) {
                const a = (i / 6) * Math.PI * 2;
                ctx.beginPath();
                ctx.moveTo(cx, cy);
                ctx.lineTo(cx + Math.cos(a) * (S / 2 - 4), cy + Math.sin(a) * (S / 2 - 4));
                ctx.stroke();
            }
            ctx.fillStyle = '#ffffff';
            ctx.beginPath();
            ctx.arc(cx, cy, 5, 0, Math.PI * 2);
            ctx.fill();
        } else {
            g.addColorStop(0, 'rgba(255,255,255,1)');
            g.addColorStop(0.5, 'rgba(255,255,255,0.6)');
            g.addColorStop(1, 'rgba(255,255,255,0)');
            ctx.fillStyle = g;
            ctx.beginPath();
            ctx.arc(cx, cy, S / 2, 0, Math.PI * 2);
            ctx.fill();
        }
        dt.hasAlpha = true;
        dt.update();
        this._textureRefs.push(dt);
        return dt;
    }

    dispose() {
        if (this._particles) try { this._particles.dispose(); } catch (e) {}
        for (const t of this._textureRefs) try { t.dispose(); } catch (e) {}
        this._textureRefs = [];
        this._particles = null;
        this._cubeMesh = null;
        this._scene3d = null;
        this.scene = null;
    }
}
