/**
 * GdPlayerModeSkin — подмена текстуры кубика игрока на "обложку режима" в ship/ball/ufo/...
 *
 * Концепция (как в GD): куб остаётся кубом, но его текстура подменяется на 2D-обложку
 * корабля/НЛО/шара когда игрок в соответствующем гейммоде.
 *
 * Сейчас реализован SHIP-режим. Остальные (ufo/ball/wave/robot) — в будущем
 * через те же фабрики (ufoSkinFactories, ballSkinFactories, …).
 *
 * Работа:
 *   1. attach(scene, scene3d, userId) — подгружает выбор из gd_ship_skin namespace.
 *   2. Рисует ship-текстуру на OffscreenCanvas → DynamicTexture.
 *   3. onBeforeRender следит за scene3d.player._shipMode:
 *      - true → сохраняет mesh.material.diffuseTexture, ставит свою.
 *      - false → восстанавливает оригинальную.
 *
 * При смене режима куб мгновенно "одевается" в корабль и обратно.
 */
import { DynamicTexture } from '@babylonjs/core';
import { SHIP_SKIN_CATALOG } from '../AdminPreview/gdShipSkins/shipSkinFactories';
import { STORYS_addres as STORYS_BASE } from '../api/API';

const PLAYER_PRIM_ID = 10001;
const SHIP_SKIN_PID = 295;
const SHIP_SKIN_NS = 'gd_ship_skin';
const DEFAULT_SHIP_SKIN = 'ss_v1';
const TEX_SIZE = 256;

export class GdPlayerModeSkin {
    constructor() {
        this.scene = null;
        this._scene3d = null;
        this._cubeMesh = null;
        this._origTexture = null;
        this._shipTexture = null;
        this._onBeforeRender = null;
        this._wasShip = false;
    }

    async attach(scene, scene3d, userId = null) {
        if (!scene || !scene3d) return;
        this.scene = scene;
        this._scene3d = scene3d;

        // Подгружаем выбор
        let skinId = DEFAULT_SHIP_SKIN;
        if (userId) {
            try {
                const url = `${STORYS_BASE}/kubikon3d/savegame/${SHIP_SKIN_PID}/${userId}/${SHIP_SKIN_NS}`;
                const r = await fetch(url, {
                    headers: { Authorization: localStorage.getItem('Authorization') || '' },
                });
                if (r.ok) {
                    const j = await r.json();
                    if (j?.data?.equipped) skinId = j.data.equipped;
                }
            } catch (e) {}
        }

        const skin = SHIP_SKIN_CATALOG.find(s => s.id === skinId) || SHIP_SKIN_CATALOG[0];

        // Рисуем DynamicTexture с обложкой корабля
        try {
            this._shipTexture = new DynamicTexture(`ship_skin_${skinId}`, { width: TEX_SIZE, height: TEX_SIZE }, scene, true);
            const ctx = this._shipTexture.getContext();
            ctx.imageSmoothingEnabled = false;
            skin.draw(ctx, '#66ff66', '#44aa44', 0);
            this._shipTexture.hasAlpha = false;
            this._shipTexture.update();
        } catch (e) {
            console.warn('[GdPlayerModeSkin] не удалось создать текстуру:', e);
            return;
        }

        // Ждём REF_BODY
        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._setupWatch();
            console.log('[GdPlayerModeSkin] прикреплён, ship-skin=', skinId);
        };
        tryAttach();
    }

    _setupWatch() {
        const player = this._scene3d?.player;
        if (!player || !this._cubeMesh) return;
        this._onBeforeRender = () => {
            const isShip = !!player._shipMode;
            if (isShip !== this._wasShip) {
                const mat = this._cubeMesh.material;
                if (!mat) { this._wasShip = isShip; return; }
                if (isShip) {
                    // Сохраняем оригинальную и накладываем ship
                    this._origTexture = mat.diffuseTexture;
                    mat.diffuseTexture = this._shipTexture;
                } else {
                    // Восстанавливаем оригинальную
                    if (this._origTexture !== null) {
                        mat.diffuseTexture = this._origTexture;
                    }
                }
                this._wasShip = isShip;
            }
        };
        this.scene.onBeforeRenderObservable.add(this._onBeforeRender);
    }

    dispose() {
        if (!this.scene) return;
        try {
            if (this._onBeforeRender) {
                this.scene.onBeforeRenderObservable.removeCallback(this._onBeforeRender);
                this._onBeforeRender = null;
            }
        } catch (e) {}
        try {
            // Восстановим оригинальную, если что
            if (this._cubeMesh?.material && this._origTexture !== null && this._wasShip) {
                this._cubeMesh.material.diffuseTexture = this._origTexture;
            }
        } catch (e) {}
        try { this._shipTexture && this._shipTexture.dispose(); } catch (e) {}
        this._shipTexture = null;
        this._cubeMesh = null;
        this._scene3d = null;
        this.scene = null;
    }
}
