import * as Cesium from 'cesium'
import { uid, degToCartesian, degsToCartesians, toCesiumColor, DEFAULT_VECTOR_LAYER_ID } from '@/map/utils/utils'

// deps: { store, layerService }
export function createEntityService(deps) {
  const { store, layerService } = deps

  const svc = {
    _ensureVectorLayer(layerId) {
      const id = layerId || DEFAULT_VECTOR_LAYER_ID
      if (!store.layers[id]) {
        return layerService
          .addLayer({ id, type: 'vector', source: null, options: { visible: true } })
          .then(() => store.layers[id].obj)
      }
      return Promise.resolve(store.layers[id].obj)
    },

    async addPoint(opts) {
      const o = opts || {}
      const ds = await this._ensureVectorLayer(o.layerId)
      const id = o.id || uid('point')
      const ent = new Cesium.Entity({
        id,
        position: degToCartesian(o.position),
        point: {
          pixelSize: o.pixelSize || 8,
          color: toCesiumColor(o.color || '#1E90FF', 1),
          heightReference: o.clampToGround
            ? Cesium.HeightReference.CLAMP_TO_GROUND
            : Cesium.HeightReference.NONE,
        },
        properties: o.properties || {},
      })
      ds.entities.add(ent)
      return id
    },

    async addPolyline(opts) {
      const o = opts || {}
      const ds = await this._ensureVectorLayer(o.layerId)
      const id = o.id || uid('line')
      const ent = new Cesium.Entity({
        id,
        polyline: {
          positions: degsToCartesians(o.positions || []),
          width: o.width || 3,
          material: toCesiumColor(o.color || '#FF4500', 1),
          clampToGround: !!o.clampToGround,
        },
        properties: o.properties || {},
      })
      ds.entities.add(ent)
      return id
    },

    async addPolygon(opts) {
      const o = opts || {}
      const ds = await this._ensureVectorLayer(o.layerId)
      const id = o.id || uid('polygon')
      const ent = new Cesium.Entity({
        id,
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(degsToCartesians(o.positions || [])),
          material: toCesiumColor(o.fillColor || 'rgba(0,191,255,0.2)'),
          outline: true,
          outlineColor: toCesiumColor(o.outlineColor || '#00BFFF', 1),
          outlineWidth: o.outlineWidth || 1,
          perPositionHeight: !(o.clampToGround === undefined ? true : o.clampToGround),
        },
        properties: o.properties || {},
      })
      ds.entities.add(ent)
      return id
    },

    async addLabel(opts) {
      const o = opts || {}
      const ds = await this._ensureVectorLayer(o.layerId)
      const id = o.id || uid('label')
      const ent = new Cesium.Entity({
        id,
        position: degToCartesian(o.position),
        label: {
          text: o.text || '',
          font: o.font || '14px sans-serif',
          fillColor: toCesiumColor(o.fillColor || '#ffffff', 1),
          outlineColor: toCesiumColor(o.outlineColor || '#000000', 1),
          outlineWidth: o.outlineWidth || 2,
          pixelOffset: o.pixelOffset || new Cesium.Cartesian2(0, -10),
        },
        properties: o.properties || {},
      })
      ds.entities.add(ent)
      return id
    },

    /**
     * 添加广告牌（Billboard）实体到地图
     * @param {Object} opts - 配置选项
     * @param {string} [opts.id] - 实体 ID，不提供则自动生成
     * @param {string} [opts.layerId] - 图层 ID，不提供则使用默认图层
     * @param {Array<number>} opts.position - 位置 [经度, 纬度] 或 [经度, 纬度, 高度]，高度默认为 0
     * @param {string} opts.image - 图片 URL 或路径
     * @param {number} [opts.width=32] - 图片宽度（像素）
     * @param {number} [opts.height=32] - 图片高度（像素）
     * @param {boolean} [opts.clampToGround=true] - 是否贴地
     * @param {Cesium.VerticalOrigin} [opts.verticalOrigin] - 垂直对齐方式
     * @param {Array<number>|Cesium.Cartesian2} [opts.pixelOffset] - 像素偏移 [x, y]
     * @param {number} [opts.disableDepthTestDistance] - 禁用深度测试的距离
     * @param {Object} [opts.properties] - 自定义属性
     * @returns {Promise<string>} 返回实体 ID
     */
    async addBillboard(opts) {
      const o = opts || {}

      // 验证必需参数
      if (!Array.isArray(o.position) || o.position.length < 2) {
        throw new Error('addBillboard 需要提供 position 参数 [经度, 纬度] 或 [经度, 纬度, 高度]')
      }

      const image = o.image || o.icon
      if (!image) {
        throw new Error('addBillboard 需要提供 image 或 icon 参数')
      }

      // 确保 position 包含高度，如果没有则默认为 0
      const position = o.position.length === 2
        ? [o.position[0], o.position[1], 0]
        : o.position

      const ds = await this._ensureVectorLayer(o.layerId)
      const id = o.id || uid('billboard')

      // 处理像素偏移
      let pixelOffset
      if (o.pixelOffset instanceof Cesium.Cartesian2) {
        pixelOffset = o.pixelOffset
      } else if (Array.isArray(o.pixelOffset)) {
        pixelOffset = new Cesium.Cartesian2(
          o.pixelOffset[0] || 0,
          o.pixelOffset[1] || 0
        )
      } else if (o.pixelOffset && typeof o.pixelOffset === 'object') {
        pixelOffset = new Cesium.Cartesian2(
          o.pixelOffset.x || 0,
          o.pixelOffset.y || 0
        )
      } else {
        pixelOffset = new Cesium.Cartesian2(0, 0)
      }

      const ent = new Cesium.Entity({
        id,
        position: degToCartesian(position),
        billboard: {
          image,
          width: o.width || 32,
          height: o.height || 32,
          verticalOrigin: o.verticalOrigin || Cesium.VerticalOrigin.BOTTOM,
          heightReference:
            o.clampToGround === false
              ? Cesium.HeightReference.NONE
              : Cesium.HeightReference.CLAMP_TO_GROUND,
          disableDepthTestDistance:
            typeof o.disableDepthTestDistance === 'number'
              ? o.disableDepthTestDistance
              : Number.POSITIVE_INFINITY,
          pixelOffset,
        },
        properties: o.properties || {},
      })

      ds.entities.add(ent)
      return id
    },

    removeEntity(entityId) {
      if (!entityId) return false
      for (const id in store.layers) {
        const rec = store.layers[id]
        if ((rec.type === 'vector' || rec.type === 'datasource') && rec.obj.entities) {
          const e = rec.obj.entities.getById(entityId)
          if (e) {
            rec.obj.entities.remove(e)
            return true
          }
        }
      }
      return false
    },

    getEntity(entityId) {
      if (!entityId) return undefined
      for (const id in store.layers) {
        const rec = store.layers[id]
        if ((rec.type === 'vector' || rec.type === 'datasource') && rec.obj.entities) {
          const e = rec.obj.entities.getById(entityId)
          if (e) return e
        }
      }
      return undefined
    },

    clearLayerEntities(layerId) {
      const id = layerId || DEFAULT_VECTOR_LAYER_ID
      const rec = store.layers[id]
      if (rec && rec.obj && rec.obj.entities) rec.obj.entities.removeAll()
    },
  }

  return svc
}

