/**
 * three-usdz-loader 完整示例
 * 需配合 Three.js 场景使用，建议使用 Vite/Webpack 等构建工具
 * 前置条件：
 * 1. 已通过 npm 安装 three three-usdz-loader
 * 2. 已部署 WASM 文件到 public/external/ 目录
 * 3. 服务器配置了正确的 COEP/COOP 头信息
 */

import { USDZLoader } from 'three-usdz-loader'
import * as THREE from 'three'

// ================= 初始化 Three.js 基础场景 =================
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
)
const renderer = new THREE.WebGLRenderer({ antialias: true })

// 初始化渲染器
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(window.devicePixelRatio)
document.querySelector('#A2demo')!.appendChild(renderer.domElement)

// 相机初始位置
camera.position.set(0, 0, 5)
camera.lookAt(0, 0, 0)

// 添加环境光（USDZ 材质需要光照）
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.position.set(0, 10, 5)
scene.add(directionalLight)

// ================= USDZ 加载器配置 =================
let currentModel: any | null = null
const modelGroup = new THREE.Group() // 用于存放加载的模型
scene.add(modelGroup)

/**
 * 初始化加载器
 * 参数说明：
 * @param wasmPath - 指定 WASM 文件的基路径（默认同源根目录）
 * 如果部署在 /public/external/ 需设置为 '/external/'
 */

let obj: any = {
  wasmPath: './external/',
  manager: new THREE.LoadingManager(() => {
    console.log('所有资源加载完成')
  })
}

const loader = new USDZLoader(obj)

// 监听加载进度
// loader.manager.onProgress = (url, loaded, total) => {
//   console.log(`加载进度: ${loaded}/${total} ${url}`)
// }

// ================= 核心加载方法 =================
/**
 * 加载 USDZ 文件
 * @param file - 通过文件输入获取的 File 对象
 */
async function loadUSDZModel(file: File) {
  try {
    // 清理旧模型（重要！防止内存泄漏）
    if (currentModel) {
      currentModel.clean()
      modelGroup.clear()
      currentModel = null
    }

    // 开始加载（第二个参数指定父容器）
    currentModel = await loader.loadFile(file, modelGroup)

    // 自动调整相机视角
    fitCameraToModel(camera, modelGroup, 1.5)

    // 处理动画
    if (currentModel.animations) {
      currentModel.animations.play() // 自动播放动画
      console.log(`检测到 ${currentModel.animations.animations.length} 个动画片段`)
    }

    console.log('模型加载成功:', currentModel)
  } catch (error) {
    console.error('模型加载失败:', error)
    // 建议在此处添加用户提示逻辑
  }
}

// ================= 工具函数 =================
/**
 * 调整相机位置适配模型
 * @param camera - 场景相机
 * @param model - 模型容器
 * @param scaleFactor - 缩放系数（建议 1-2）
 */
function fitCameraToModel(
  camera: THREE.PerspectiveCamera,
  model: THREE.Group,
  scaleFactor: number
) {
  const bbox = new THREE.Box3().expandByObject(model)
  const center = bbox.getCenter(new THREE.Vector3())
  const size = bbox.getSize(new THREE.Vector3()).length()

  camera.position.copy(center)
  camera.position.z += size * scaleFactor
  camera.lookAt(center)

  // 更新相机参数
  camera.near = size / 100
  camera.far = size * 100
  camera.updateProjectionMatrix()
}

// ================= 清理资源 =================
function cleanupScene() {
  if (currentModel) {
    currentModel.animations?.stop() // 停止动画
    currentModel.clean() // 销毁几何体和材质
    modelGroup.clear() // 移除所有子对象
    currentModel = null
  }
  renderer.dispose() // 释放 WebGL 资源
}

// ================= 渲染循环 =================
function animate() {
  requestAnimationFrame(animate)
  renderer.render(scene, camera)
}
animate()

// ================= 窗口尺寸变化处理 =================
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
})

// ================= 示例：通过文件输入触发加载 =================
// 在 HTML 中添加：<input type="file" id="usdzInput" accept=".usdz" />
const fileInput = document.getElementById('usdzInput') as HTMLInputElement
fileInput.addEventListener('change', async e => {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (file && file.name.endsWith('.usdz')) {
    await loadUSDZModel(file)
  }
})

// 在页面卸载时清理资源
window.addEventListener('beforeunload', cleanupScene)
