import * as THREE from 'three';
import { 
  boldGlassMaterial, 
  boldWireframeMaterial, 
  innovationGlassMaterial, 
  frostedGlassMaterial, 
  lightOrangeMaterial 
} from './materialDefinitions.js';
import { boldRoughnessAnimation, innovationGlassAnimation } from './animationManager.js';

// Apply materials based on model type
export function applyMaterials(model, modelType) {
  console.log(`=== Material Assignment Debug for ${modelType} ===`);
  let meshCount = 0;
  model.traverse((object) => {
    if (object.isMesh) {
      meshCount++;
      console.log(`Found mesh: "${object.name}"`);
      const previousMaterial = object.material;
      object.castShadow = true;
      object.receiveShadow = true;

      if (modelType === 'bold') {
        // Bold-specific material logic
        if (object.name === 'Cube') {
          console.log(` → Applying bold glass material to "${object.name}"`);
          object.material = boldGlassMaterial.clone();
          object.material.side = THREE.DoubleSide;
          object.material.depthWrite = false;
          object.renderOrder = 2;
          // Store material reference for roughness animation
          boldRoughnessAnimation.materials.push(object.material);
        } else if (object.name === 'Cubewire') {
          console.log(` → Applying wireframe material to "${object.name}"`);
          object.material = boldWireframeMaterial.clone();
          object.renderOrder = 1;
        } else {
          console.log(` → Applying bold glass material (fallback) to "${object.name}"`);
          object.material = boldGlassMaterial.clone();
          // Store material reference for roughness animation
          boldRoughnessAnimation.materials.push(object.material);
        }
      } else if (modelType === 'innovation') {
        // Innovation-specific material logic
        const orangeMeshes = ['dblsc', 'ec', 'gemini', 'infinity', 'star', 'dpd'];
        const targetGlassNames = ['Cube.alt90.df'];
        const sanitize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, '');
        const nameMatches = (name, targets) => {
          const clean = sanitize(name);
          return targets.some((t) => {
            const ct = sanitize(t);
            return clean === ct || clean.includes(ct) || ct.includes(clean);
          });
        };

        if (nameMatches(object.name, targetGlassNames)) {
          // Create outer glass shell with innovation-specific material
          object.material = innovationGlassMaterial.clone();
          object.material.side = THREE.DoubleSide;
          object.material.depthWrite = false;
          object.renderOrder = 2;
          // Store material reference for animation
          innovationGlassAnimation.materials.push(object.material);
          // Create inner glass shell
          const innerShell = object.clone();
          innerShell.material = innovationGlassMaterial.clone();
          innerShell.material.side = THREE.DoubleSide;
          innerShell.material.depthWrite = false;
          innerShell.material.transmission = 0.8;
          innerShell.renderOrder = 1;
          innerShell.scale.multiplyScalar(0.95);
          // Store inner shell material reference for animation too
          innovationGlassAnimation.materials.push(innerShell.material);
          object.parent.add(innerShell);
        } else if (nameMatches(object.name, orangeMeshes)) {
          object.material = lightOrangeMaterial.clone();
          object.renderOrder = 0;
        }
      } else {
        // Agility and Storytelling use frosted glass material for all meshes
        if (object.name.startsWith('base')) {
          console.log(` → Applying frosted glass material to "${object.name}"`);
          object.material = frostedGlassMaterial.clone();
        } else {
          console.log(` → Applying frosted glass material (fallback) to "${object.name}"`);
          object.material = frostedGlassMaterial.clone();
        }
      }

      object.material.needsUpdate = true;
      // Cleanup previous materials
      if (Array.isArray(previousMaterial)) {
        previousMaterial.forEach((mat) => mat && mat.dispose && mat.dispose());
      } else if (previousMaterial && previousMaterial.dispose) {
        previousMaterial.dispose();
      }
    }
  });
  console.log(`Total meshes processed: ${meshCount}`);
  console.log(`=== End Material Assignment Debug for ${modelType} ===`);
}

// Center and frame model with camera
export function centerAndFrameModel(model, targetCamera, controls) {
  const box = new THREE.Box3().setFromObject(model);
  const center = box.getCenter(new THREE.Vector3());
  model.position.sub(center);
  model.updateMatrixWorld(true);

  // Only set camera position if it's not already positioned (avoid reset during transitions)
  // Use fixed camera distance that's further away from the origin
  const fixedCameraDistance = 50; // Fixed distance, much further than before
  // Calculate isometric-like position with 35-degree angles
  const angle = 35 * Math.PI / 180; // Convert 35 degrees to radians
  const cosAngle = Math.cos(angle);
  const x = fixedCameraDistance * cosAngle;
  const y = fixedCameraDistance * cosAngle;
  const z = fixedCameraDistance * cosAngle;

  targetCamera.position.set(x, y, z);
  controls.target.set(0, 0, 0);
  // Set distance limits to lock the camera at this distance
  controls.minDistance = fixedCameraDistance;
  controls.maxDistance = fixedCameraDistance;
  controls.update();

  console.log(`Camera positioned at: x=${x}, y=${y}, z=${z}, distance=${fixedCameraDistance}`);
}

// Setup animations based on model type
export function setupAnimations(model, gltf, modelType) {
  if (gltf.animations && gltf.animations.length > 0) {
    const animMixer = new THREE.AnimationMixer(model);
    gltf.animations.forEach((clip) => {
      const action = animMixer.clipAction(clip);
      if (modelType === 'bold') {
        // Play once for bold
        action.loop = THREE.LoopOnce;
        action.clampWhenFinished = true;
        action.play();
        console.log(`Bold animation started: ${clip.name}`);
      } else if (modelType === 'innovation') {
        // PingPong loop for innovation
        action.loop = THREE.LoopPingPong;
        action.play();
        console.log(`Innovation animation started: ${clip.name} (PingPong)`);
      } else if (modelType === 'agility') {
        // Regular loop for agility
        action.loop = THREE.LoopRepeat;
        action.play();
        console.log(`Agility animation started: ${clip.name} (Loop)`);
      } else if (modelType === 'storytelling') {
        // Play once for storytelling
        action.loop = THREE.LoopOnce;
        action.clampWhenFinished = true;
        action.play();
        console.log(`Storytelling animation started: ${clip.name}`);
      }
    });
    if (modelType === 'innovation') {
      animMixer.timeScale = 3.0; // Keep existing timeScale for innovation
      console.log('Innovation animation timeScale set to 3.0');
    }
    return animMixer;
  }
  return null;
}

// Reset mesh geometry to original state
export function resetMeshGeometry(mesh) {
  if (!mesh || !mesh.geometry || !mesh.geometry.userData.originalPositions) {
    return;
  }
  const positions = mesh.geometry.attributes.position;
  const original = mesh.geometry.userData.originalPositions;
  for (let i = 0; i < positions.count; i++) {
    positions.setXYZ(i, original[i * 3], original[i * 3 + 1], original[i * 3 + 2]);
  }
  positions.needsUpdate = true;
  mesh.geometry.computeVertexNormals();
}

// FIXED: Clean up geometry data completely
export function cleanupGeometryData(model) {
  if (!model) return;
  model.traverse((object) => {
    if (object.isMesh && object.geometry && object.geometry.userData) {
      delete object.geometry.userData.originalPositions;
      delete object.geometry.userData.originalWorldPositions;
      delete object.geometry.userData.inverseWorldMatrix;
    }
  });
}

// Create model from preloaded data - FIXED: Always create fresh geometry
export function createModelFromPreloaded(modelType, preloadedModels, camera, controls) {
  const preloadedData = preloadedModels[modelType];
  if (!preloadedData) {
    console.error(`Preloaded model not found: ${modelType}`);
    return { model: null, animMixer: null };
  }

  console.log(`Creating model from preloaded data: ${modelType}`);
  // Clear animation materials arrays when creating new models
  if (modelType === 'bold') {
    boldRoughnessAnimation.materials = [];
  } else if (modelType === 'innovation') {
    innovationGlassAnimation.materials = [];
  }

  // Clone the scene deeply to ensure fresh geometry
  const model = preloadedData.scene.clone(true);
  // IMPORTANT: Clone all geometries to ensure they're independent
  model.traverse((object) => {
    if (object.isMesh && object.geometry) {
      object.geometry = object.geometry.clone();
    }
  });

  // Apply materials
  applyMaterials(model, modelType);
  // Setup animations
  const animMixer = setupAnimations(model, preloadedData.gltf, modelType);
  // Center and frame model
  centerAndFrameModel(model, camera, controls);

  console.log(`Model created successfully: ${modelType}`);
  return { model, animMixer };
}
