import { ref } from 'vue'
import * as Cesium from 'cesium'
import { getModelCompareConfig } from '../config/modelCompare.config'

/**
 * 3D Tiles加载管理 Composable
 * 负责加载灾前/灾后3D模型数据，并支持分屏对比功能
 */
export function use3DTiles() {
  const beforeTileset = ref(null)
  const afterTileset = ref(null)

  /**
   * 加载3D Tileset
   * @param {Cesium.Viewer} viewer - Cesium Viewer 实例
   * @param {string} sceneType - 场景类型：'before' 或 'after'
   * @param {boolean} autoZoom - 是否自动缩放到模型（默认false，保持用户设置的相机位置）
   * @param {Cesium.SplitDirection} splitDirection - 分割方向（默认为 NONE）
   */
  const load3DTileset = async (viewer, sceneType = 'after', autoZoom = false, splitDirection = Cesium.SplitDirection.NONE) => {
    if (!viewer) return null

    try {
      console.log(`[use3DTiles] 正在加载${sceneType === 'after' ? '灾后' : '灾前'}3D模型...`)

      // 从配置中获取 URL
      const config = getModelCompareConfig()
      const tilesetConfig = sceneType === 'after' ? config.after3DTiles : config.before3DTiles
      const url = tilesetConfig.url

      const tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
        skipLevelOfDetail: true,
        baseScreenSpaceError: 1024,
        skipScreenSpaceErrorFactor: 16,
        skipLevels: 1,
        immediatelyLoadDesiredLevelOfDetail: false,
        loadSiblings: false,
        maximumScreenSpaceError: 2.0,  // 降低到2.0以提高模型精细度（原来是16.0）
        dynamicScreenSpaceError: true, // 启用动态屏幕空间误差调整
        dynamicScreenSpaceErrorDensity: 0.00278, // 启用密度调整
        dynamicScreenSpaceErrorFactor: 4.0, // 动态因子
        foveatedScreenSpaceError: true, // 启用视锥细化
        foveatedConeSize: 0.1, // 视锥大小
        foveatedMinimumScreenSpaceErrorRelaxation: 0.0 // 最小放松
      })

      // 将tileset添加到viewer的primitives
      viewer.scene.primitives.add(tileset)

      // 设置splitDirection（用于对比模式）
      tileset.splitDirection = splitDirection

      if (sceneType === 'after') {
        afterTileset.value = tileset
      } else {
        beforeTileset.value = tileset
      }

      console.log(`[use3DTiles] ${sceneType === 'after' ? '灾后' : '灾前'}3D模型加载成功，splitDirection: ${splitDirection}`)

      // 只有明确要求时才自动缩放到tileset
      if (autoZoom) {
        await viewer.zoomTo(tileset)
      }

      return tileset
    } catch (error) {
      console.error(`[use3DTiles] 加载${sceneType === 'after' ? '灾后' : '灾前'}3D模型失败:`, error)
      return null
    }
  }

  /**
   * 等待 Tileset 完全就绪（包括首批瓦片加载）
   *
   * 这个函数确保：
   * 1. Tileset 本身已就绪（readyPromise）
   * 2. 初始视图的所有瓦片已加载完成（initialTilesLoaded）
   *
   * @param {Cesium.Cesium3DTileset} tileset - 要等待的 Tileset
   * @param {number} timeout - 超时时间（毫秒），默认10秒
   * @returns {Promise<void>}
   */
  const waitForTilesetReady = async (tileset, timeout = 10000) => {
    if (!tileset) {
      console.warn('[use3DTiles] waitForTilesetReady: tileset 为空')
      return
    }

    let timeoutId = null
    let eventHandler = null

    // 统一清理函数
    const cleanup = () => {
      if (timeoutId) {
        clearTimeout(timeoutId)
        timeoutId = null
      }
      if (eventHandler) {
        tileset.initialTilesLoaded.removeEventListener(eventHandler)
        eventHandler = null
      }
    }

    try {
      // 步骤1：等待 Tileset 基础就绪
      await tileset.readyPromise
      console.log('[use3DTiles] Tileset readyPromise 已完成')

      // 步骤2：早期出口 - 快速检查
      if (tileset.tilesLoaded) {
        console.log('[use3DTiles] 瓦片已加载，直接继续')
        return
      }

      // 步骤3：等待初始瓦片加载完成（带超时）
      console.log('[use3DTiles] 等待初始瓦片加载...')

      await Promise.race([
        // 等待 initialTilesLoaded 事件
        new Promise((resolve) => {
          eventHandler = () => {
            console.log('[use3DTiles] 初始瓦片加载完成（事件触发）')
            cleanup()
            resolve()
          }
          tileset.initialTilesLoaded.addEventListener(eventHandler)
        }),

        // 超时机制
        new Promise((_, reject) => {
          timeoutId = setTimeout(() => {
            cleanup()
            reject(new Error(`等待瓦片加载超时（${timeout}ms）`))
          }, timeout)
        })
      ])

      console.log('[use3DTiles] Tileset 已完全就绪')
    } catch (error) {
      if (error.message && error.message.includes('超时')) {
        // 超时但继续执行（保持原有行为）
        console.warn(`[use3DTiles] ${error.message}，继续执行`)
      } else {
        console.error('[use3DTiles] 等待 Tileset 就绪失败:', error)
      }
      // 即使失败也不抛出异常，允许程序继续执行
    } finally {
      cleanup() // 保险清理
    }
  }

  /**
   * 移除3D Tileset
   */
  const remove3DTileset = (viewer, sceneType) => {
    if (!viewer) return

    const tileset = sceneType === 'after' ? afterTileset.value : beforeTileset.value
    if (tileset) {
      viewer.scene.primitives.remove(tileset)
      if (sceneType === 'after') {
        afterTileset.value = null
      } else {
        beforeTileset.value = null
      }
      console.log(`[use3DTiles] ${sceneType === 'after' ? '灾后' : '灾前'}3D模型已移除`)
    }
  }

  /**
   * 更新 Tileset 的 splitDirection
   * @param {string} sceneType - 场景类型：'before' 或 'after'
   * @param {Cesium.SplitDirection} splitDirection - 新的分割方向
   */
  const updateTilesetSplitDirection = (sceneType, splitDirection) => {
    const tileset = sceneType === 'after' ? afterTileset.value : beforeTileset.value
    if (tileset) {
      tileset.splitDirection = splitDirection
      console.log(`[use3DTiles] ${sceneType === 'after' ? '灾后' : '灾前'}3D模型 splitDirection 已更新为: ${splitDirection}`)
    } else {
      console.warn(`[use3DTiles] ${sceneType === 'after' ? '灾后' : '灾前'}3D模型不存在，无法更新 splitDirection`)
    }
  }

  return {
    beforeTileset,
    afterTileset,
    load3DTileset,
    waitForTilesetReady,
    remove3DTileset,
    updateTilesetSplitDirection
  }
}

export default use3DTiles
