import React, { Suspense, useEffect, useMemo, useRef ,useState} from 'react'
import { Canvas, useThree } from '@react-three/fiber'
import { OrbitControls, Html, useGLTF, Bounds, useFBX, useAnimations } from '@react-three/drei'
import * as THREE from 'three'

// 轨道控制器，限制缩放比和距离
function ControlsWithLimits({ controlsRef, zoomMin, zoomMax, baseDistance }) {
  const { camera } = useThree()
  // autoRotateSpeed!==0即自动旋转
  const [autoRotateSpeed,setAutoRotateSpeed] = useState(0)
  useEffect(() => {
    const controls = controlsRef.current
    if (!controls || baseDistance == null) return
    controls.maxDistance = baseDistance * Math.max(1, zoomMin)
  }, [camera, controlsRef, baseDistance, zoomMin, zoomMax])
  useEffect(()=>{
    window.sceneFc = {
      resetView: () => {
        if (controlsRef.current) {
          controlsRef.current.reset()
        }
      },
      setAutoRotate: (speed = 1.0) => {
        const clampedSpeed = Math.max(0.1, Math.min(8, Number(speed) || 1))
        setAutoRotateSpeed(clampedSpeed)
      }
    }
  },[])
  // 添加双击归位
  useEffect(() => {
    const onDoubleClick = () => {
      if (controlsRef.current) {
        console.log(123)
        controlsRef.current.reset()
      }
    }
    window.addEventListener('dblclick', onDoubleClick)
    return () => window.removeEventListener('dblclick', onDoubleClick)
  }, [controlsRef])

  return (
    <OrbitControls
      ref={controlsRef}
      enableDamping
      dampingFactor={0.08}
      rotateSpeed={0.8}
      zoomSpeed={1.0}
      enableZoom
      enablePan
      panSpeed={0.8}
      screenSpacePanning
      touches={{
        ONE: THREE.TOUCH.ROTATE,
        TWO: THREE.TOUCH.DOLLY_PAN
      }}
      makeDefault
      autoRotate={!!autoRotateSpeed}
      autoRotateSpeed={autoRotateSpeed}
    />
  )
}

// glb/gltf文件加载
function Model({ url }) {
  const { scene, animations } = useGLTF(url, true)
  const ref = useRef()
  const { actions, names } = useAnimations(animations, ref)
  useEffect(() => {
    if (!actions || !names || names.length === 0) return
    const a = actions[names[0]]
    if (a) {
      a.reset()
      a.play()
    }
  }, [actions, names])
  return <primitive ref={ref} object={scene} />
}

// fbx文件加载
function FBXModel({ url }) {
  const obj = useFBX(url)
  const ref = useRef()
  const { actions, names } = useAnimations(obj.animations || [], ref)
  useEffect(() => {
    if (!actions || !names || names.length === 0) return
    const a = actions[names[0]]
    if (a) {
      a.reset()
      a.play()
    }
  }, [actions, names])
  return <primitive ref={ref} object={obj} />
}

// 方便模型类型
function pickModel(url) {
  const u = (url || '').toLowerCase()
  const clean = u.split('?')[0].split('#')[0]
  if (clean.endsWith('.fbx')) return 'fbx'
  return 'gltf'
}

// 场景
function Scene({ url, zoomMin, zoomMax }) {
  const controlsRef = useRef()
  const { camera ,gl} = useThree()
  const [baseDistance, setBaseDistance] = useState(null)
  const [initialState, setInitialState] = useState(null)  // 保存 fit 后的初始相机 + target

  const kind = pickModel(url)

  // 平滑复位函数
  const resetToInitial = () => {
    if (!controlsRef.current || !initialState) {
      console.warn('无法复位：controls 或 initialState 未就绪')
      return
    }

    const controls = controlsRef.current

    const startPos = camera.position.clone()
    const startTarget = controls.target.clone()
    const endPos = initialState.position
    const endTarget = initialState.target

    let t = 0
    const duration = 800  // ms，可调
    const startTime = performance.now()

    const animate = (time) => {
      const elapsed = time - startTime
      t = Math.min(elapsed / duration, 1)

      camera.position.lerpVectors(startPos, endPos, t)
      controls.target.lerpVectors(startTarget, endTarget, t)
      controls.update()

      if (t < 1) {
        requestAnimationFrame(animate)
      }
    }

    requestAnimationFrame(animate)
  }

  // 监听模型适应大小后，回调确认位置
function FitWatcher({ controlsRef, onBase }) {
  const { camera } = useThree()

  useEffect(() => {
    if (!controlsRef.current) return

    let rafId
    let attempts = 0
    const maxAttempts = 30  // 防死循环，大约 0.5 秒

    const tryCapture = () => {
      const controls = controlsRef.current
      const d = camera.position.distanceTo(controls.target)

      // 如果连续几帧距离几乎不变，就认为 fit 完成了
      if (Math.abs(d - (window.lastD || d)) < 0.001 && attempts > 5) {
        onBase(d)
        setTimeout(() => {
      if (!initialState && controlsRef.current) {
        console.log(controlsRef.current.target.clone())
        setInitialState({
          position: camera.position.clone(),
          target: controlsRef.current.target.clone(),
        })
        console.log('稳定后保存初始状态：', camera.position)
      }
    }, 300)
        return
      }

      window.lastD = d
      attempts++
      if (attempts < maxAttempts) {
        rafId = requestAnimationFrame(tryCapture)
      }
    }

    rafId = requestAnimationFrame(tryCapture)

    return () => {
      cancelAnimationFrame(rafId)
      delete window.lastD
    }
  }, [onBase, camera, controlsRef])

  return null
}

  // 在 fit 完成后保存初始状态
  useEffect(() => {
     setTimeout(() => {
     setInitialState({
        position: camera.position.clone(),
        target: controlsRef.current.target.clone(),
      })
     }, 200);
    if (baseDistance && !initialState && controlsRef.current) {
      console.log(camera.position.clone(),controlsRef.current.target.clone())
      setInitialState({
        position: camera.position.clone(),
        target: controlsRef.current.target.clone(),
      })
    }
  }, [baseDistance, camera, initialState])

  // 暴露到 window（只暴露一次，组件卸载时清理）
  useEffect(() => {
    // 创建或覆盖 window.sceneFc
    window.sceneFc = window.sceneFc || {}
    window.sceneFc.reset = resetToInitial

    console.log('window.sceneFc.reset 已暴露，可外部调用')

    return () => {
      // 清理（可选，但推荐）
      if (window.sceneFc && window.sceneFc.reset === resetToInitial) {
        delete window.sceneFc.reset
      }
    }
  }, [resetToInitial])  // 依赖 resetToInitial，确保函数稳定

  // 双击复位监听（使用 click 事件判断双击，更可靠）
  useEffect(() => {
    let lastClickTime = 0
    let clickCount = 0
    let timeoutId

    const handleClick = (e) => {
      const now = Date.now()

      // 如果点击在 OrbitControls 控制区域内（避免误触 UI）
      if (e.target !== gl.domElement) return

      clickCount++

      if (clickCount === 1) {
        timeoutId = setTimeout(() => {
          clickCount = 0
        }, 300)
      }

      if (clickCount === 2) {
        clearTimeout(timeoutId)
        clickCount = 0

        // 阻止默认行为（如果有）
        e.preventDefault()
        e.stopPropagation()

        resetToInitial()
      }

      lastClickTime = now
    }

    const dom = gl.domElement
    dom.addEventListener('click', handleClick)

    return () => {
      dom.removeEventListener('click', handleClick)
    }
  }, [gl, resetToInitial])

  return (
    <>
      <ambientLight intensity={0.8} />
      <directionalLight position={[5, 5, 5]} intensity={1.0} />
      {url ? (
        <Suspense
          fallback={
            <Html center style={{ color: '#222', fontSize: 14 }}>
              模型加载中…
            </Html>
          }
        >
          <Bounds fit clip observe margin={1.2}>
            {kind === 'fbx' ? <FBXModel url={url} /> : kind === 'usdz' ? <USDZModel url={url} /> : <Model url={url} />}
            <ControlsWithLimits controlsRef={controlsRef} zoomMin={zoomMin} zoomMax={zoomMax} baseDistance={baseDistance} />
            <FitWatcher controlsRef={controlsRef} onBase={setBaseDistance} />
          </Bounds>
        </Suspense>
      ) : (
        <>
          <ControlsWithLimits controlsRef={controlsRef} zoomMin={zoomMin} zoomMax={zoomMax} baseDistance={baseDistance} />
          <FitWatcher controlsRef={controlsRef} onBase={setBaseDistance} />
          <Html center style={{ color: '#222', fontSize: 14 }}>
            请在地址栏提供 ?src=GLB地址
          </Html>
        </>
      )}
    </>
  )
}

export default Scene