<template>
  <div ref="container" class="w-full h-full cursor-move rounded-xl overflow-hidden transition-colors duration-500" :style="{ backgroundColor: backgroundColor }" title="Drag to rotate" />
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from "vue";
import * as THREE from "three";
import { STLLoader } from "three/addons/loaders/STLLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { getHexColor } from "@/lib/colors";

interface Props {
  file: File;
  color?: string; // Color name or hex
}

const props = defineProps<Props>();
const container = ref<HTMLElement | null>(null);
let animationId = 0;
let renderer: THREE.WebGLRenderer | null = null;
let mesh: THREE.Mesh | null = null;

const isLight = (hex: string) => {
  const color = hex.startsWith("#") ? hex : getHexColor(hex);
  const rgb = parseInt(color.slice(1, 7), 16);
  const r = (rgb >> 16) & 0xff;
  const g = (rgb >> 8) & 0xff;
  const b = (rgb >> 0) & 0xff;
  const luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  return luma > 150;
};

const backgroundColor = computed(() => {
  if (!props.color) return "transparent";
  return isLight(props.color) ? "#0f172a" : "#f8fafc";
});

watch(() => props.color, (newColor) => {
  if (mesh && mesh.material instanceof THREE.MeshPhongMaterial) {
    const hex = getHexColor(newColor);
    mesh.material.color.set(hex);
  }
});

onMounted(() => {
  if (!container.value) return;

  const width = container.value.clientWidth || 80;
  const height = container.value.clientHeight || 80;

  const scene = new THREE.Scene();

  const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 2000);
  camera.position.set(0, 0, 150);

  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  renderer.setSize(width, height);
  renderer.setClearColor(0x000000, 0);
  container.value.appendChild(renderer.domElement);

  const controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.autoRotate = true;
  controls.autoRotateSpeed = 3.0;

  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1.2);
  hemiLight.position.set(0, 200, 0);
  scene.add(hemiLight);

  const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
  dirLight.position.set(100, 200, 100);
  scene.add(dirLight);

  const loader = new STLLoader();
  const objectUrl = URL.createObjectURL(props.file);
  
  loader.load(objectUrl, (geometry) => {
    geometry.center();
    geometry.computeVertexNormals();

    const hex = getHexColor(props.color);
    const material = new THREE.MeshPhongMaterial({ 
      color: hex,
      specular: 0x222222, 
      shininess: 60 
    });
    
    mesh = new THREE.Mesh(geometry, material);
    
    geometry.computeBoundingSphere();
    const radius = geometry.boundingSphere?.radius || 50;
    const scale = 50 / radius;
    mesh.scale.set(scale, scale, scale);

    scene.add(mesh);
    URL.revokeObjectURL(objectUrl);
  });

  const animate = () => {
    animationId = requestAnimationFrame(animate);
    controls.update();
    if (renderer) renderer.render(scene, camera);
  };
  animate();

  const handleResize = () => {
    if (!container.value || !renderer) return;
    const w = container.value.clientWidth;
    const h = container.value.clientHeight;
    camera.aspect = w / h;
    camera.updateProjectionMatrix();
    renderer.setSize(w, h);
  };

  window.addEventListener("resize", handleResize);

  onUnmounted(() => {
    cancelAnimationFrame(animationId);
    window.removeEventListener("resize", handleResize);
    if (renderer && renderer.domElement.parentNode) {
      renderer.domElement.parentNode.removeChild(renderer.domElement);
    }
    renderer?.dispose();
  });
});
</script>
