// Preview-режим скина — пустой мир, дефолтный персонаж, на нём
// проверяемый аксессуар.
// Подфаза 3.4 RUBLOX_ACCESSORY_ATTACHMENT_PLAN.md (2026-05-26).
//
// Открывается из team.rublox.pro/designer/skins по кнопке «Тестировать»:
//   https://player.rublox.pro/_preview-skin/<itemId>#team_jwt=<JWT>
//
// PlayerAuth уже умеет принимать team_jwt из hash и сохранять в localStorage —
// ничего дополнительно делать не надо.
//
// Что НЕ грузим (в отличие от KubikonPlayer):
//   - проект (нет game data)
//   - мультиплеер
//   - чат / leaderboard / GameHud / Hotbar / KubikonBugReport
//   - perf-overlay
//
// Что грузим:
//   - BabylonScene + плоская земля (там же)
//   - дефолтный body-скин (skin_bacon-hair)
//   - аксессуар через player.equipAccessory(item)

import { useEffect, useRef, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useAuth } from '../auth/PlayerAuth';
import { BabylonScene } from '../engine/BabylonScene';
import * as Kubikon3DApi from '../api/Kubikon3DService';
import LoadingScreen from '../LoadingScreen';

const DEFAULT_BODY_SKIN = 'skin_bacon-hair';

export default function PreviewSkinRoute() {
  const { itemId } = useParams();
  const navigate = useNavigate();
  const { isAuthenticated, isLoading: authLoading, error: authError } = useAuth();

  const canvasRef = useRef(null);
  const sceneRef = useRef(null);
  const [item, setItem] = useState(null);
  const [loadErr, setLoadErr] = useState(null);
  const [phase, setPhase] = useState('auth');   // auth | loading | ready | error

  // Грузим item, как только авторизация прошла
  useEffect(() => {
    if (!isAuthenticated) return;
    setPhase('loading');
    Kubikon3DApi.getDesignerSkin(itemId)
      .then((r) => {
        const it = r?.data?.item || r?.data || r;
        if (!it || !it.path) throw new Error('Скин не найден или нет path');
        setItem(it);
      })
      .catch((e) => {
        // eslint-disable-next-line no-console
        console.error('[PreviewSkin] load item failed', e);
        const msg = e?.response?.data?.message
                 || e?.response?.data?.error
                 || e?.message || 'Не удалось загрузить скин';
        setLoadErr(msg);
        setPhase('error');
      });
  }, [isAuthenticated, itemId]);

  // Создаём сцену и применяем аксессуар когда item готов
  useEffect(() => {
    if (!item || !canvasRef.current) return;
    if (sceneRef.current) return;  // уже создана

    let scene;
    let destroyed = false;
    (async () => {
      try {
        scene = new BabylonScene(canvasRef.current);
        sceneRef.current = scene;
        scene.init();
        // Подфаза 3.6: если item — body-skin (shirt/pants/полное тело),
        // используем его как ТЕЛО персонажа через setPlayerModelType('body:<id>').
        // Иначе — обычный дефолт + аксессуар сверху.
        if (item.is_body_skin) {
          try { scene.setPlayerModelType?.(`body:${item.id}`); } catch (e) {}
        } else {
          try { scene.setPlayerModelType?.(DEFAULT_BODY_SKIN); } catch (e) {}
        }
        // Запускаем play-mode чтобы создался PlayerController
        scene.enterPlayMode?.();
        await _waitForPlayerReady(scene);
        if (destroyed) return;
        const player = scene.player || scene._player;
        if (!item.is_body_skin && player
            && typeof player.equipAccessory === 'function') {
          // Обычный аксессуар: накладываем на дефолтное тело.
          await player.equipAccessory(item);
        }
        if (!destroyed) setPhase('ready');
      } catch (e) {
        // eslint-disable-next-line no-console
        console.error('[PreviewSkin] scene init failed', e);
        if (!destroyed) {
          setLoadErr(e?.message || 'Ошибка инициализации сцены');
          setPhase('error');
        }
      }
    })();

    return () => {
      destroyed = true;
      try {
        if (scene && typeof scene.dispose === 'function') scene.dispose();
        else if (scene && scene.engine) scene.engine.dispose();
      } catch (e) {}
      sceneRef.current = null;
    };
  }, [item]);

  // ─── рендер ────────────────────────────────────────────────────────

  if (authLoading) return <LoadingScreen text="Подключение" />;
  if (authError === 'no_jwt_local') {
    return (
      <LoadingScreen
        text="Нужен JWT"
        subText="Открой из team.rublox.pro кнопкой «Тестировать» — она пришлёт JWT в URL."
      />
    );
  }
  if (!isAuthenticated) {
    return (
      <LoadingScreen
        text="Сессия истекла"
        subText="Вернись в team.rublox.pro и попробуй снова."
      />
    );
  }

  return (
    <div style={{ position: 'fixed', inset: 0, background: '#000' }}>
      <canvas ref={canvasRef}
              style={{ width: '100%', height: '100%', display: 'block',
                       touchAction: 'none', outline: 'none' }}/>

      {/* Баннер сверху */}
      <div style={bannerStyle}>
        <div style={{ fontWeight: 700, fontSize: 14 }}>
          Превью скина: «{item ? item.name : '...'}»
        </div>
        <div style={{ fontSize: 12, opacity: 0.7, marginTop: 2 }}>
          {item ? `${SKIN_TYPE_RU[item.type] || item.type} · код ${item.code}` : ''}
          {item && item.status !== 'published' && (
            <span style={{ color: '#ffcc66', marginLeft: 8 }}>
              · {item.status === 'draft' ? 'черновик' : 'на проверке'} — виден только тебе
            </span>
          )}
        </div>
        <button onClick={() => { window.close(); navigate('/'); }}
                style={closeBtnStyle}>
          Закрыть
        </button>
      </div>

      {phase === 'loading' && (
        <div style={overlayStyle}>
          <div>Загрузка сцены...</div>
        </div>
      )}
      {phase === 'error' && (
        <div style={overlayStyle}>
          <div style={{ color: '#ff8888', fontWeight: 700, marginBottom: 8 }}>
            Не удалось загрузить превью
          </div>
          <div style={{ fontSize: 13, opacity: 0.85, maxWidth: 420, textAlign: 'center' }}>
            {loadErr}
          </div>
          <button onClick={() => window.close()} style={{ ...closeBtnStyle, marginTop: 12, position: 'static' }}>
            Закрыть
          </button>
        </div>
      )}
    </div>
  );
}

const SKIN_TYPE_RU = {
  hat: 'Шляпа', tool: 'Инструмент', hair: 'Причёска',
  face: 'Лицо', shirt: 'Рубашка', pants: 'Штаны',
};

const bannerStyle = {
  position: 'absolute', top: 12, left: 12,
  background: 'rgba(10, 14, 26, 0.88)', color: '#f1f5fb',
  padding: '10px 16px 10px 14px',
  borderRadius: 8, border: '1px solid rgba(255,255,255,0.10)',
  fontFamily: '"Roboto Condensed", system-ui, sans-serif',
  maxWidth: 'calc(100vw - 40px)',
};
const closeBtnStyle = {
  position: 'absolute', top: 8, right: 8,
  background: 'rgba(255, 111, 122, 0.18)', color: '#ff6f7a',
  border: '1px solid rgba(255, 111, 122, 0.40)',
  borderRadius: 6, padding: '4px 10px',
  fontSize: 12, fontWeight: 700, cursor: 'pointer',
};
const overlayStyle = {
  position: 'absolute', inset: 0,
  background: 'rgba(0,0,0,0.65)', color: '#fff',
  display: 'flex', alignItems: 'center', justifyContent: 'center',
  flexDirection: 'column', fontFamily: 'system-ui, sans-serif',
};

/** Ждём 5 секунд пока scene.player.getAccessoryManager() станет доступен.
 *  PlayerController._loadPlayerModel — async, AccessoryManager создаётся
 *  в его конце.
 */
async function _waitForPlayerReady(scene, timeoutMs = 5000) {
  const start = Date.now();
  while (Date.now() - start < timeoutMs) {
    const p = scene.player || scene._player;
    if (p && typeof p.equipAccessory === 'function'
        && typeof p.getAccessoryManager === 'function'
        && p.getAccessoryManager() != null) {
      return p;
    }
    await new Promise((r) => setTimeout(r, 60));
  }
  return scene.player || scene._player || null;
}
