export function createSierpinskiPyramid(THREE, config, scene) {
  const maxDepth = config.maxDepth ?? 5;
  const baseSize = config.baseSize ?? 4.0;
  const explosionFactor = config.explosionFactor ?? 0.0;
  const rotationSpeed = config.animation?.rotationSpeed ?? 0.2;
  const pulseSpeed = config.animation?.pulseSpeed ?? 1.0;
  const pulseAmount = config.animation?.pulseAmount ?? 0.1;
  const colorCycleSpeed = config.animation?.colorCycleSpeed ?? 0.5;
  
  // Colors per depth level
  const colors = config.colors || {};
  const baseColor = new THREE.Color(colors.base || '#ff4488');
  const midColor = new THREE.Color(colors.mid || '#44ff88');
  const tipColor = new THREE.Color(colors.tip || '#4488ff');
  const emissiveColor = new THREE.Color(colors.emissive || '#220033');
  const emissiveIntensity = colors.emissiveIntensity ?? 0.5;
  
  // Material
  const metalness = config.material?.metalness ?? 0.8;
  const roughness = config.material?.roughness ?? 0.2;
  const envMapIntensity = config.material?.envMapIntensity ?? 0.8;
  const envMapPath = config.material?.envMap || null;
  let envMapTexture = null;
  if (envMapPath) {
    const loader = new THREE.TextureLoader();
    envMapTexture = loader.load('/' + envMapPath);
    envMapTexture.mapping = THREE.EquirectangularReflectionMapping;
  }
  
  const pyramidGroup = new THREE.Group();
  
  // Tetrahedron vertices (regular tetrahedron centered at origin)
  const sqrt2 = Math.sqrt(2);
  const sqrt3 = Math.sqrt(3);
  const tetraVertices = [
    new THREE.Vector3(1, 0, -1/sqrt2),
    new THREE.Vector3(-1, 0, -1/sqrt2),
    new THREE.Vector3(0, 1, 1/sqrt2),
    new THREE.Vector3(0, -1, 1/sqrt2)
  ];
  
  // Collect all tetrahedron transforms
  const tetraMatrices = [];
  const tetraDepths = [];
  
  function generateSierpinski(center, size, depth) {
    if (depth > maxDepth) return;
    
    if (depth === maxDepth) {
      // Store this tetrahedron
      const matrix = new THREE.Matrix4();
      matrix.compose(
        center,
        new THREE.Quaternion(),
        new THREE.Vector3(size, size, size)
      );
      tetraMatrices.push(matrix);
      tetraDepths.push(depth);
      return;
    }
    
    // Recurse into 4 corners
    const newSize = size / 2;
    for (let i = 0; i < 4; i++) {
      const offset = tetraVertices[i].clone().multiplyScalar(newSize);
      const newCenter = center.clone().add(offset);
      generateSierpinski(newCenter, newSize, depth + 1);
    }
  }
  
  generateSierpinski(new THREE.Vector3(0, 0, 0), baseSize, 0);
  
  console.log(`[Sierpinski] Generated ${tetraMatrices.length} tetrahedrons at depth ${maxDepth}`);
  
  // Create instanced tetrahedron geometry
  const tetraGeo = new THREE.TetrahedronGeometry(1, 0);
  
  const tetraMaterial = new THREE.ShaderMaterial({
    uniforms: {
      uTime: { value: 0 },
      uExplosion: { value: explosionFactor },
      uRotationSpeed: { value: rotationSpeed },
      uPulseSpeed: { value: pulseSpeed },
      uPulseAmount: { value: pulseAmount },
      uColorCycleSpeed: { value: colorCycleSpeed },
      uBaseColor: { value: baseColor },
      uMidColor: { value: midColor },
      uTipColor: { value: tipColor },
      uEmissiveColor: { value: emissiveColor },
      uEmissiveIntensity: { value: emissiveIntensity },
      uMetalness: { value: metalness },
      uRoughness: { value: roughness },
      uEnvMapIntensity: { value: envMapIntensity },
      uEnvMap: { value: envMapTexture },
      uHasEnvMap: { value: envMapTexture ? 1.0 : 0.0 },
      uMaxDepth: { value: maxDepth },
    },
    vertexShader: `
      attribute float instanceDepth;
      
      uniform float uTime;
      uniform float uExplosion;
      uniform float uRotationSpeed;
      uniform float uPulseSpeed;
      uniform float uPulseAmount;
      uniform float uMaxDepth;
      
      varying vec3 vNormal;
      varying vec3 vWorldPos;
      varying vec3 vViewDir;
      varying vec3 vReflect;
      varying float vDepth;
      
      mat3 rotateY(float angle) {
        float c = cos(angle);
        float s = sin(angle);
        return mat3(c, 0, s, 0, 1, 0, -s, 0, c);
      }
      
      mat3 rotateX(float angle) {
        float c = cos(angle);
        float s = sin(angle);
        return mat3(1, 0, 0, 0, c, -s, 0, s, c);
      }
      
      void main() {
        vDepth = instanceDepth;
        
        vec3 instancePos = vec3(instanceMatrix[3][0], instanceMatrix[3][1], instanceMatrix[3][2]);
        float instanceScale = length(vec3(instanceMatrix[0][0], instanceMatrix[1][0], instanceMatrix[2][0]));
        
        vec3 explosionDir = normalize(instancePos + vec3(0.001));
        vec3 explodedPos = instancePos + explosionDir * uExplosion * instanceScale * 2.0;
        
        float rotAngle = uTime * uRotationSpeed;
        mat3 rot = rotateY(rotAngle) * rotateX(rotAngle * 0.7);
        
        float pulse = 1.0 + sin(uTime * uPulseSpeed + instanceDepth) * uPulseAmount;
        
        vec3 rotatedPos = rot * position * instanceScale * pulse;
        vec3 worldPos = rotatedPos + explodedPos;
        
        vWorldPos = worldPos;
        vViewDir = normalize(cameraPosition - worldPos);
        vNormal = normalize(rot * normal);
        vReflect = reflect(-vViewDir, vNormal);
        
        gl_Position = projectionMatrix * viewMatrix * vec4(worldPos, 1.0);
      }
    `,
    fragmentShader: `
      uniform float uTime;
      uniform float uColorCycleSpeed;
      uniform vec3 uBaseColor;
      uniform vec3 uMidColor;
      uniform vec3 uTipColor;
      uniform vec3 uEmissiveColor;
      uniform float uEmissiveIntensity;
      uniform float uMetalness;
      uniform float uRoughness;
      uniform float uEnvMapIntensity;
      uniform sampler2D uEnvMap;
      uniform float uHasEnvMap;
      uniform float uMaxDepth;
      
      varying vec3 vNormal;
      varying vec3 vWorldPos;
      varying vec3 vViewDir;
      varying vec3 vReflect;
      varying float vDepth;
      
      #define PI 3.14159265359
      
      vec3 sampleEnvMap(vec3 dir) {
        float phi = atan(dir.z, dir.x);
        float theta = acos(clamp(dir.y, -1.0, 1.0));
        vec2 uv = vec2((phi + PI) / (2.0 * PI), theta / PI);
        return texture2D(uEnvMap, uv).rgb;
      }
      
      void main() {
        float depthNorm = vDepth / uMaxDepth;
        float cycle = sin(uTime * uColorCycleSpeed + depthNorm * 3.14159) * 0.5 + 0.5;
        
        vec3 baseColor;
        if (depthNorm < 0.5) {
          baseColor = mix(uBaseColor, uMidColor, depthNorm * 2.0);
        } else {
          baseColor = mix(uMidColor, uTipColor, (depthNorm - 0.5) * 2.0);
        }
        baseColor = mix(baseColor, uTipColor, cycle * 0.3);
        
        vec3 normal = normalize(vNormal);
        vec3 viewDir = normalize(vViewDir);
        vec3 lightDir = normalize(vec3(1.0, 1.0, 0.5));
        vec3 halfDir = normalize(lightDir + viewDir);
        
        // Fresnel
        float fresnel = pow(1.0 - max(dot(normal, viewDir), 0.0), 3.0);
        
        float NdotL = max(dot(normal, lightDir), 0.0);
        float ambient = 0.2;
        
        float specPower = mix(256.0, 8.0, uRoughness);
        float specular = pow(max(dot(normal, halfDir), 0.0), specPower);
        
        vec3 diffuseColor = baseColor * (1.0 - uMetalness);
        vec3 specularColor = mix(vec3(0.04), baseColor, uMetalness);
        
        vec3 color = diffuseColor * (ambient + NdotL * 0.6);
        color += specularColor * specular * (1.0 - uRoughness * 0.5);
        
        // Environment map reflection
        if (uHasEnvMap > 0.5) {
          vec3 envColor = sampleEnvMap(normalize(vReflect));
          color += specularColor * envColor * fresnel * uEnvMapIntensity;
        } else {
          color += specularColor * fresnel * uEnvMapIntensity;
        }
        
        color += uEmissiveColor * uEmissiveIntensity * (0.5 + cycle * 0.5);
        
        gl_FragColor = vec4(color, 1.0);
      }
    `,
    side: THREE.DoubleSide,
  });
  
  const tetraMesh = new THREE.InstancedMesh(tetraGeo, tetraMaterial, tetraMatrices.length);
  
  const depthArray = new Float32Array(tetraMatrices.length);
  for (let i = 0; i < tetraMatrices.length; i++) {
    tetraMesh.setMatrixAt(i, tetraMatrices[i]);
    depthArray[i] = tetraDepths[i];
  }
  tetraMesh.instanceMatrix.needsUpdate = true;
  tetraGeo.setAttribute('instanceDepth', new THREE.InstancedBufferAttribute(depthArray, 1));
  
  pyramidGroup.add(tetraMesh);
  pyramidGroup.userData.tetraMesh = tetraMesh;
  pyramidGroup.userData.config = config;
  
  // Position
  if (config.position) {
    pyramidGroup.position.set(config.position.x ?? 0, config.position.y ?? 0, config.position.z ?? 0);
  }
  if (config.rotation) {
    pyramidGroup.rotation.set(
      (config.rotation.x ?? 0) * Math.PI / 180,
      (config.rotation.y ?? 0) * Math.PI / 180,
      (config.rotation.z ?? 0) * Math.PI / 180
    );
  }
  
  scene.add(pyramidGroup);
  return pyramidGroup;
}
