/**
 * GdSkinsPreview — превью всех GD-скинов куба разом.
 *
 * Маршрут: /admin-preview/gd-skins
 *
 * Каждый скин — отдельная мини-Babylon-сцена с вращающимся кубом.
 * Текстура куба — DynamicTexture из canvas-фабрики (CUBE_SKINS[*].draw).
 * Глобальный переключатель цветов (primary/secondary) применяется ко всем.
 *
 * Анимированные скины (cube_flame, cube_cat) перерисовывают canvas каждый кадр.
 */
import React, { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../auth/AuthContext.jsx';
import styles from './GdSkinsPreview.module.css';
import {
  CUBE_SKINS, CUBE_TRAILS, SKIN_COLORS,
  DEFAULT_PRIMARY, DEFAULT_SECONDARY,
  renderSkin,
} from './gdSkins/cubeSkinFactories';

import { Engine } from '@babylonjs/core/Engines/engine';
import { Scene } from '@babylonjs/core/scene';
import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera';
import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight';
import { DirectionalLight } from '@babylonjs/core/Lights/directionalLight';
import { Vector3, Color3, Color4 } from '@babylonjs/core/Maths/math';
import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder';
import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';

const CUBE_SIZE = 1.2;

/**
 * Карточка одного скина куба.
 * Принимает skin + текущие primary/secondary цвета (могут меняться сверху).
 */
function CubeSkinCard({ skin, primary, secondary }) {
  const canvasRef = useRef(null);
  const textureCanvasRef = useRef(null);   // отдельный 2D-canvas для DynamicTexture

  useEffect(() => {
    if (!canvasRef.current) return;
    let engine = null;

    // 2D-canvas для текстуры (off-screen)
    const tex2d = document.createElement('canvas');
    tex2d.width = 256;
    tex2d.height = 256;
    textureCanvasRef.current = tex2d;

    engine = new Engine(canvasRef.current, true, { preserveDrawingBuffer: true });
    const scene = new Scene(engine);
    scene.clearColor = new Color4(0.12, 0.14, 0.20, 1);

    // Камера
    const cam = new ArcRotateCamera('cam',
      -Math.PI / 4, Math.PI / 2.8, 3.0,
      new Vector3(0, 0, 0), scene);
    cam.attachControl(canvasRef.current, true);
    cam.wheelPrecision = 50;
    cam.lowerRadiusLimit = 1.8;
    cam.upperRadiusLimit = 6;

    // Свет
    const hemi = new HemisphericLight('h', new Vector3(0, 1, 0), scene);
    hemi.intensity = 0.6;
    hemi.groundColor = new Color3(0.3, 0.3, 0.4);
    const dir = new DirectionalLight('d', new Vector3(-0.5, -1, -0.3), scene);
    dir.intensity = 0.7;

    // Куб
    const cube = MeshBuilder.CreateBox('cube', { size: CUBE_SIZE }, scene);
    const mat = new StandardMaterial('mat', scene);
    const dt = new DynamicTexture('dt_' + skin.id, { width: 256, height: 256 }, scene, false);
    mat.diffuseTexture = dt;
    mat.specularColor = new Color3(0.1, 0.1, 0.1);
    cube.material = mat;

    // Платформа под кубом
    const ground = MeshBuilder.CreateDisc('ground', { radius: 1.4, tessellation: 32 }, scene);
    ground.rotation.x = Math.PI / 2;
    ground.position.y = -CUBE_SIZE / 2 - 0.01;
    const gmat = new StandardMaterial('gmat', scene);
    gmat.diffuseColor = new Color3(0.2, 0.22, 0.28);
    ground.material = gmat;

    let time = 0;
    let stopped = false;

    const refreshTexture = (t) => {
      const ctx = tex2d.getContext('2d');
      renderSkin(tex2d, skin.id, primary, secondary, t);
      // копируем в DynamicTexture
      const dtCtx = dt.getContext();
      dtCtx.drawImage(tex2d, 0, 0);
      dt.update(false);
    };

    refreshTexture(0);

    scene.onBeforeRenderObservable.add(() => {
      cube.rotation.y += 0.005;
      cube.rotation.x = Math.sin(time * 0.5) * 0.15;
      time += engine.getDeltaTime() / 1000;
      if (skin.animated) refreshTexture(time);
    });

    engine.runRenderLoop(() => {
      if (!stopped) scene.render();
    });
    const onResize = () => engine.resize();
    window.addEventListener('resize', onResize);

    return () => {
      stopped = true;
      window.removeEventListener('resize', onResize);
      try { engine.dispose(); } catch (_) {}
    };
  }, [skin.id, primary, secondary]);

  return (
    <div className={styles.card}>
      <div className={styles.header}>
        <h3 className={styles.title}>{skin.title}</h3>
        <span className={styles.category}>{skin.category}</span>
      </div>
      <div className={styles.canvasWrap}>
        <canvas ref={canvasRef} className={styles.canvas} />
      </div>
      <div className={styles.meta}>
        <span className={styles.price}>
          {skin.priceStars === 0 ? 'бесплатно' : `⭐ ${skin.priceStars}`}
        </span>
        {skin.animated && <span className={styles.animated}>🎬 анимация</span>}
        <code className={styles.skinId}>{skin.id}</code>
      </div>
    </div>
  );
}

/**
 * Карточка trail-эффекта.
 * Показывает движущийся куб с шлейфом из частиц (для визуального теста).
 */
function TrailCard({ trail }) {
  const canvasRef = useRef(null);

  useEffect(() => {
    if (!canvasRef.current) return;
    let engine = null;
    let stopped = false;

    (async () => {
      const { ParticleSystem } = await import('@babylonjs/core/Particles/particleSystem');
      const { Texture } = await import('@babylonjs/core/Materials/Textures/texture');

      engine = new Engine(canvasRef.current, true, { preserveDrawingBuffer: true });
      const scene = new Scene(engine);
      scene.clearColor = new Color4(0.12, 0.14, 0.20, 1);

      const cam = new ArcRotateCamera('cam',
        -Math.PI / 2 - 0.1, Math.PI / 2.5, 4,
        new Vector3(0, 0, 0), scene);
      cam.attachControl(canvasRef.current, true);

      const hemi = new HemisphericLight('h', new Vector3(0, 1, 0), scene);
      hemi.intensity = 0.7;

      // Куб который бегает по горизонтали — оставляет след
      const cube = MeshBuilder.CreateBox('cube', { size: 0.6 }, scene);
      const mat = new StandardMaterial('m', scene);
      mat.diffuseColor = new Color3(0.4, 1.0, 0.4);
      cube.material = mat;

      // Дисочек-пол
      const g = MeshBuilder.CreateGround('g', { width: 6, height: 1.5 }, scene);
      g.position.y = -0.4;
      const gmat = new StandardMaterial('gm', scene);
      gmat.diffuseColor = new Color3(0.2, 0.22, 0.28);
      g.material = gmat;

      // Текстура частицы (просто белый круг)
      const partCanvas = document.createElement('canvas');
      partCanvas.width = 64; partCanvas.height = 64;
      const pctx = partCanvas.getContext('2d');
      const grad = pctx.createRadialGradient(32, 32, 0, 32, 32, 32);
      grad.addColorStop(0, 'rgba(255,255,255,1)');
      grad.addColorStop(1, 'rgba(255,255,255,0)');
      pctx.fillStyle = grad;
      pctx.fillRect(0, 0, 64, 64);
      const partTex = new DynamicTexture('partTex', { width: 64, height: 64 }, scene, false);
      partTex.getContext().drawImage(partCanvas, 0, 0);
      partTex.update(false);

      const ps = new ParticleSystem('ps', 200, scene);
      ps.particleTexture = partTex;
      ps.emitter = cube;
      ps.minEmitBox = new Vector3(0, 0, 0);
      ps.maxEmitBox = new Vector3(0, 0, 0);
      ps.emitRate = trail.params.emissionRate;
      ps.minLifeTime = trail.params.lifetime * 0.7;
      ps.maxLifeTime = trail.params.lifetime;
      ps.minSize = trail.params.sizeStart * 0.6;
      ps.maxSize = trail.params.sizeStart;
      ps.direction1 = new Vector3(-0.3, -0.3, 0);
      ps.direction2 = new Vector3(-0.7, 0.3, 0);
      ps.minEmitPower = 0.4;
      ps.maxEmitPower = 0.8;
      ps.gravity = new Vector3(0, -0.5, 0);

      // Цвета частиц
      const parseHex = (h) => {
        const r = parseInt(h.slice(1, 3), 16) / 255;
        const g = parseInt(h.slice(3, 5), 16) / 255;
        const b = parseInt(h.slice(5, 7), 16) / 255;
        return new Color4(r, g, b, 1);
      };
      if (trail.params.colorStart === 'rainbow') {
        // радуга — цикл по цветам
        ps.color1 = new Color4(1, 0.3, 0.3, 1);
        ps.color2 = new Color4(0.3, 0.6, 1, 1);
        ps.colorDead = new Color4(1, 1, 1, 0);
      } else {
        ps.color1 = parseHex(trail.params.colorStart);
        ps.color2 = parseHex(trail.params.colorStart);
        const cd = parseHex(trail.params.colorEnd);
        cd.a = 0;
        ps.colorDead = cd;
      }
      ps.start();

      // Куб двигается по дуге туда-сюда
      let t = 0;
      scene.onBeforeRenderObservable.add(() => {
        t += engine.getDeltaTime() / 1000;
        cube.position.x = Math.sin(t * 1.5) * 1.5;
        cube.rotation.y = t;
        cube.rotation.z = t * 0.7;
        // Для радуги — циклически меняем цвет
        if (trail.params.colorStart === 'rainbow') {
          const r = 0.5 + 0.5 * Math.sin(t * 2);
          const g = 0.5 + 0.5 * Math.sin(t * 2 + 2);
          const b = 0.5 + 0.5 * Math.sin(t * 2 + 4);
          ps.color1 = new Color4(r, g, b, 1);
          ps.color2 = new Color4(g, b, r, 1);
        }
      });

      engine.runRenderLoop(() => { if (!stopped) scene.render(); });
      const onResize = () => engine.resize();
      window.addEventListener('resize', onResize);
    })();

    return () => {
      stopped = true;
      if (engine) {
        try { engine.dispose(); } catch (_) {}
      }
    };
  }, [trail.id]);

  return (
    <div className={styles.card}>
      <div className={styles.header}>
        <h3 className={styles.title}>{trail.title}</h3>
        <span className={styles.category}>Trail</span>
      </div>
      <div className={styles.canvasWrap}>
        <canvas ref={canvasRef} className={styles.canvas} />
      </div>
      <div className={styles.meta}>
        <span className={styles.price}>
          {trail.priceStars === 0 ? 'бесплатно' : `⭐ ${trail.priceStars}`}
        </span>
        <code className={styles.skinId}>{trail.id}</code>
      </div>
    </div>
  );
}


function GdSkinsPreview() {
  const { userRole, isLoading } = useAuth();
  const navigate = useNavigate();
  const [primary, setPrimary] = useState(DEFAULT_PRIMARY);
  const [secondary, setSecondary] = useState(DEFAULT_SECONDARY);

  if (isLoading) return <div className={styles.loading}>Загрузка...</div>;
  if (userRole !== 'admin') {
    return (
      <div className={styles.denied}>
        <h2>Доступ только для администратора</h2>
        <button onClick={() => navigate('/')} className={styles.backBtn}>На главную</button>
      </div>
    );
  }

  return (
    <div className={styles.root}>
      <div className={styles.topbar}>
        <h1 className={styles.h1}>GD-Скины куба — превью {CUBE_SKINS.length} дизайнов + {CUBE_TRAILS.length} trail</h1>
        <div className={styles.subline}>
          Все скины генерируются программно через canvas (cubeSkinFactories.js) — никаких PNG-файлов
        </div>
      </div>

      {/* Палитра цветов */}
      <div className={styles.colorBar}>
        <div className={styles.colorGroup}>
          <span className={styles.colorLabel}>Основной:</span>
          {SKIN_COLORS.map(c => (
            <button
              key={'p_' + c.id}
              className={primary === c.hex ? styles.colorBtnActive : styles.colorBtn}
              style={{ background: c.hex }}
              onClick={() => setPrimary(c.hex)}
              title={c.title}
            />
          ))}
        </div>
        <div className={styles.colorGroup}>
          <span className={styles.colorLabel}>Контур:</span>
          {SKIN_COLORS.map(c => (
            <button
              key={'s_' + c.id}
              className={secondary === c.hex ? styles.colorBtnActive : styles.colorBtn}
              style={{ background: c.hex }}
              onClick={() => setSecondary(c.hex)}
              title={c.title}
            />
          ))}
        </div>
        <button
          className={styles.resetBtn}
          onClick={() => { setPrimary(DEFAULT_PRIMARY); setSecondary(DEFAULT_SECONDARY); }}
        >Сброс</button>
      </div>

      <h2 className={styles.h2}>Скины куба ({CUBE_SKINS.length})</h2>
      <div className={styles.grid}>
        {CUBE_SKINS.map(s => (
          <CubeSkinCard key={s.id} skin={s} primary={primary} secondary={secondary} />
        ))}
      </div>

      <h2 className={styles.h2}>Trail-эффекты ({CUBE_TRAILS.length})</h2>
      <div className={styles.grid}>
        {CUBE_TRAILS.map(t => (
          <TrailCard key={t.id} trail={t} />
        ))}
      </div>

      <div className={styles.footer}>
        <p>Тащи мышью на любой карточке — куб крутится руками. Меняй цвета сверху — все скины обновятся синхронно.</p>
        <p>Если нужны правки — скажи МИНу, я подкручу canvas-функции в <code>cubeSkinFactories.js</code>.</p>
      </div>
    </div>
  );
}

export default GdSkinsPreview;
