'use client'

import React, { useEffect, useRef, useState, useCallback } from 'react'
import {
  Engine,
  Scene,
  Vector3,
  HemisphericLight,
  ArcRotateCamera,
  MeshBuilder,
  StandardMaterial,
  Color3,
  Color4,
  AbstractMesh,
  Mesh,
  Nullable,
  SceneLoader
} from '@babylonjs/core'
import '@babylonjs/loaders'
import { getCacheFileName, loadCachedData, parseAndCacheScene, ParsedMeshData } from '../utils/meshCache'

interface ModelViewerProps {
  modelPath: string
  onModelLoaded?: (modelData: {
    meshes: AbstractMesh[]
    boundingBox: {
      min: { x: number; y: number; z: number }
      max: { x: number; y: number; z: number }
    }
  }) => void
  onError?: (error: string) => void
}

const ModelViewer: React.FC<ModelViewerProps> = ({
  modelPath,
  onModelLoaded,
  onError
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const engineRef = useRef<Nullable<Engine>>(null)
  const sceneRef = useRef<Nullable<Scene>>(null)
  const [isLoading, setIsLoading] = useState(false)
  const isInitializedRef = useRef(false)
  const isDisposedRef = useRef(false)



  useEffect(() => {
    isDisposedRef.current = false
    isInitializedRef.current = false
    return () => {
      isDisposedRef.current = true
    }
  }, [])

  useEffect(() => {
    if (!canvasRef.current || isInitializedRef.current) return

    const canvas = canvasRef.current
    const engine = new Engine(canvas, true)
    engineRef.current = engine

    const scene = new Scene(engine)
    sceneRef.current = scene

    scene.clearColor = new Color4(0.1, 0.1, 0.15, 1)

    const camera = new ArcRotateCamera('camera', 0, Math.PI / 3, 20, Vector3.Zero(), scene)
    camera.attachControl(canvas, true)
    camera.lowerRadiusLimit = 2
    camera.upperRadiusLimit = 200
    camera.wheelDeltaPercentage = 0.01
    camera.panningSensibility = 50
    camera.angularSensibilityX = 1000
    camera.angularSensibilityY = 1000

    const ambientLight = new HemisphericLight('ambientLight', new Vector3(0, 1, 0), scene)
    ambientLight.intensity = 0.4
    ambientLight.diffuse = new Color3(0.7, 0.7, 0.8)
    ambientLight.specular = new Color3(0.2, 0.2, 0.3)
    ambientLight.groundColor = new Color3(0.3, 0.3, 0.4)

    const keyLight = new HemisphericLight('keyLight', new Vector3(1, 1, 0), scene)
    keyLight.intensity = 0.6
    keyLight.diffuse = new Color3(1, 1, 0.9)
    keyLight.specular = new Color3(1, 1, 0.9)

    const fillLight = new HemisphericLight('fillLight', new Vector3(-1, 0.5, -1), scene)
    fillLight.intensity = 0.3
    fillLight.diffuse = new Color3(0.8, 0.8, 1)

    engine.runRenderLoop(() => {
      if (!isDisposedRef.current) {
        scene.render()
      }
    })

    const handleResize = () => {
      if (!isDisposedRef.current) {
        engine.resize()
      }
    }
    window.addEventListener('resize', handleResize)

    isInitializedRef.current = true

    return () => {
      isDisposedRef.current = true
      isInitializedRef.current = false
      window.removeEventListener('resize', handleResize)
      if (engineRef.current) {
        engineRef.current.dispose()
        engineRef.current = null
      }
      sceneRef.current = null
    }
  }, [])

  useEffect(() => {
    if (!isInitializedRef.current || !modelPath || isDisposedRef.current) {
      return
    }

    const loadModel = async () => {
      if (!sceneRef.current || isDisposedRef.current) {
        return
      }

      setIsLoading(true)
      console.log('🚀 Loading GLTF model:', modelPath)
      
      try {
        const cacheFileName = getCacheFileName(modelPath)
        const cachedData = await loadCachedData(cacheFileName)

        if (cachedData) {
          console.log('📦 Using cached mesh data for analysis')
        } else {
          console.log('🔄 No cached data found, parsing scene...')
        }
        
        const result = await SceneLoader.ImportMeshAsync(
          '',
          modelPath,
          '',
          sceneRef.current
        )

        console.log('✅ GLTF Model loaded successfully!')
        console.log('📊 Loaded Meshes:', result.meshes.length)
        
        if (result.meshes.length > 0) {
          
          const boundingBox = result.meshes[0].getHierarchyBoundingVectors()
          const size = boundingBox.max.subtract(boundingBox.min)
          const maxDimension = Math.max(size.x, size.y, size.z)
          
          const camera = sceneRef.current!.activeCamera as ArcRotateCamera
          camera.radius = maxDimension * 2
          camera.target = result.meshes[0].position
          
                     const parsedData = await parseAndCacheScene(result.meshes, cacheFileName, modelPath)
          
          onModelLoaded?.({
            meshes: result.meshes,
            boundingBox: {
              min: boundingBox.min,
              max: boundingBox.max
            }
          })

          console.log('🎉 Model ready for viewing!')
        } else {
          console.warn('⚠️ No meshes found in model')
          onError?.('No geometry found in model')
        }
      } catch (error) {
        console.error('❌ Error loading GLTF model:', error)
        onError?.(`Failed to load model: ${error}`)
      } finally {
        if (!isDisposedRef.current) {
          setIsLoading(false)
        }
      }
    }

    loadModel()
  }, [modelPath])

  return (
    <div className="w-full h-screen relative bg-gray-900 overflow-hidden">
      <canvas
        ref={canvasRef}
        className="w-full h-full outline-none block"
      />
      {isLoading && (
        <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-black/80 text-white px-8 py-5 rounded-xl z-50 flex items-center gap-3 text-base font-medium">
          <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
          Loading Model...
        </div>
      )}
    </div>
  )
}

export default ModelViewer 