/**
 * GdPortalArch — рендер 3D-арок поверх портал-примитивов (gd_ship, gd_cube, …).
 *
 * Работа:
 *   1. attach(scene, scene3d) пробегает по primitiveManager.instances.
 *   2. Для каждого primitive с typeDef.kind === 'gd_portal':
 *      - Читает выбор юзера: gd_portal_choices[gdMode] (например 'ship_v3').
 *      - Если выбора нет — берёт дефолт `${gdMode}_v1`.
 *      - Спавнит арку из PORTAL_CATALOG в той же позиции.
 *      - Скрывает оригинальный mesh (visible=false), но НЕ удаляет — GdLevelManager
 *        читает позицию из primitiveManager и обрабатывает коллизию.
 *
 * Загрузка выбора:
 *   GET /api/v1/storys/kubikon3d/savegame/295/<userId>/gd_portal_choices
 *   data = { cube: 'cube_v5', ship: 'ship_v5', ... }
 *
 * Дефолты (если нет выбора):
 *   все группы = `${gdMode}_v1` (классический).
 */
import { Vector3, TransformNode } from '@babylonjs/core';
import { PORTAL_CATALOG } from '../AdminPreview/gdPortals/portalFactories';
import { STORYS_addres as STORYS_BASE } from '../api/API';

// project_id выбора порталов = 295 (sandbox-проект, где юзер выбирал)
const PORTAL_CHOICES_PID = 295;
const PORTAL_CHOICES_NS = 'gd_portal_choices';

const DEFAULT_PORTAL_BY_MODE = {
    cube:  'cube_v1',
    ship:  'ship_v1',
    ball:  'ball_v1',
    ufo:   'ufo_v1',
    wave:  'wave_v1',
    robot: 'robot_v1',
};

export class GdPortalArch {
    constructor() {
        this.scene = null;
        this._scene3d = null;
        this._instances = [];   // [{ portalPrimId, handle }]
        this._choices = null;
    }

    /**
     * Привязать к сцене.
     * userId — для загрузки выбора порталов из savegame (project_id=295, ns=gd_portal_choices).
     * Если userId не передан или загрузка не удалась — используются дефолты `${mode}_v1`.
     */
    async attach(scene, scene3d, userId = null) {
        if (!scene || !scene3d) return;
        this.scene = scene;
        this._scene3d = scene3d;
        this._choices = {};
        if (userId) {
            try {
                const url = `${STORYS_BASE}/kubikon3d/savegame/${PORTAL_CHOICES_PID}/${userId}/${PORTAL_CHOICES_NS}`;
                const r = await fetch(url, {
                    headers: { Authorization: localStorage.getItem('Authorization') || '' },
                });
                if (r.ok) {
                    const j = await r.json();
                    this._choices = j?.data || {};
                }
            } catch (e) {
                console.warn('[GdPortalArch] не загрузил выбор:', e);
            }
        }
        // Откладываем — примитивы могут быть не созданы в момент enterPlayMode
        let attempts = 0;
        const tryRender = () => {
            attempts++;
            const pm = scene3d.primitiveManager;
            if (!pm || !pm.instances) {
                if (attempts < 10) setTimeout(tryRender, 200);
                return;
            }
            this._renderAll();
        };
        tryRender();
    }

    _renderAll() {
        const pm = this._scene3d.primitiveManager;
        if (!pm || !pm.instances) return;
        let rendered = 0;
        for (const data of pm.instances.values()) {
            // type у primitive — строка вроде 'gd_ship', 'gd_cube'.
            // У этих типов в PrimitiveTypes.js kind = 'gd_portal' и есть gdMode.
            // Импортировать getPrimitiveType из engine — там есть.
            // Но проще проверить по type-строке:
            const portalType = data.type || '';
            const m = portalType.match(/^gd_(\w+)$/);
            if (!m) continue;
            const gdMode = m[1];   // 'cube', 'ship', …
            if (!DEFAULT_PORTAL_BY_MODE[gdMode]) continue;   // не порталовый

            const chosenId = (this._choices && this._choices[gdMode]) || DEFAULT_PORTAL_BY_MODE[gdMode];
            const factory = PORTAL_CATALOG.find(p => p.id === chosenId);
            if (!factory) {
                console.warn('[GdPortalArch] не найдена фабрика:', chosenId);
                continue;
            }
            try {
                const handle = factory.make(this.scene, `portal_inst_${data.id}`);
                if (!handle || !handle.root) continue;
                // Низ колонн на y=0; ставим на y=1 (поверх пола), как GdStartArch
                handle.root.position = new Vector3(data.x, 1, data.z);
                // Поворот по Y 90° — фабрики строят арку проёмом вдоль X (колонны на ±X).
                // Игрок бежит по +X — арка должна стоять поперёк, колонны на ±Z, проём вдоль X.
                handle.root.rotation.y = Math.PI / 2;
                // Скрыть оригинальный primitive-меш (GdLevelManager всё ещё видит data.x для коллизии)
                if (data.mesh) {
                    data.mesh.setEnabled(false);
                }
                this._instances.push({ portalPrimId: data.id, handle });
                rendered++;
            } catch (e) {
                console.warn('[GdPortalArch] ошибка при создании арки:', chosenId, e);
            }
        }
        console.log(`[GdPortalArch] отрисовано ${rendered} порталов`);
    }

    dispose() {
        for (const inst of this._instances) {
            try { inst.handle && inst.handle.dispose && inst.handle.dispose(); } catch (e) {}
        }
        this._instances = [];
        this.scene = null;
        this._scene3d = null;
    }
}
