import * as Cesium from 'cesium';

import type { HCesiumManager } from './HCesiumManager';
import type { I卫星 } from './HCesiumManager.types';

import { type OrbitCalculationResult, SatelliteCalculator } from '../calculators/SatelliteCalculator';

interface ManagedSatelliteEntities {
  coverageEntity?: Cesium.Entity;
  mainEntity: Cesium.Entity;
  orbitEntity?: Cesium.Entity;
}

export class HCesiumSatelliteManager {
  private viewerManager: HCesiumManager;
  private calculator: SatelliteCalculator;
  // 用于存储当前由此管理器管理的卫星相关实体的 Map
  private currentSatelliteEntities: Map<string, ManagedSatelliteEntities> = new Map();

  constructor(viewerManager: HCesiumManager, calculator: SatelliteCalculator) {
    this.viewerManager = viewerManager;
    this.calculator = calculator;
  }

  /**
   * 向视图中添加或更新卫星实体及其相关元素（轨道、覆盖范围）。
   * 注意：当前实现仅添加，如果已存在则警告并返回现有实体。
   */
  addOrUpdateSatellite(options: I卫星): undefined {
    const existingEntry = this.currentSatelliteEntities.get(options.id);
    const { id, tle, showOrbit, showCoverage } = options;

    // --- 如果实体已存在，直接返回，不处理更新 ---
    if (existingEntry) {
      console.warn(`ID 为 "${options.id}" 的卫星实体已存在，跳过添加。`);
      return;
    }
    // --- 解析 TLE 和计算轨道 ---
    const satrec = this.calculator.parseTle(tle, id);
    if (!satrec) {
      return undefined; // 解析失败，已打印错误
    }

    const viewer = this.viewerManager.getViewer();
    if (!viewer) {
      console.error('Viewer 未初始化，无法计算轨道。');
      return undefined;
    }
    const startTime = viewer.clock.currentTime; // 使用当前 viewer 的时间作为起点

    const orbitResult: null | OrbitCalculationResult = this.calculator.calculateOrbit(satrec, startTime, options, id);

    if (!orbitResult) {
      console.error(`计算卫星 ${id} 的轨道失败。`);
      return undefined;
    }
    const { sampledPositionProperty, orbitPositions } = orbitResult;
    // --- 计算结束 ---

    // --- 从 TLE 提取名称 ---
    const tleLines = tle.trim().split('\n') as [string, string, string];
    const name = tleLines[0].trim();
    // --- 提取结束 ---

    const randomBaseColor = Cesium.Color.fromRandom({ alpha: 1 }); // 确保 alpha 为 1

    // 创建卫星实体
    const satelliteEntity = this._createSatelliteEntity(id, name, sampledPositionProperty, randomBaseColor, options);

    // --- 创建覆盖范围实体 (如果需要) ---
    let coverageEntity: Cesium.Entity | null | undefined;
    if (showCoverage) {
      coverageEntity = this._createCoverageEntity(id, name, sampledPositionProperty, randomBaseColor);
    }
    // --- 创建结束 ---

    // 添加完整轨道线（如果需要）
    let orbitEntity: Cesium.Entity | undefined;
    if (showOrbit && orbitPositions.length > 1) {
      orbitEntity = this._createOrbitEntity(id, name, orbitPositions, randomBaseColor);
    }
    // --- 创建结束 ---

    // --- 添加到 Viewer ---
    const addedMainEntity = this.viewerManager.addEntity(satelliteEntity);
    if (!addedMainEntity) {
      console.error(`通过 ViewerManager 添加卫星主体 ID 为 "${id}" 的实体失败。`);
      return undefined; // 主实体添加失败则中止
    }

    let addedCoverageEntity: Cesium.Entity | null = null;
    if (coverageEntity) {
      addedCoverageEntity = this.viewerManager.addEntity(coverageEntity);
      if (!addedCoverageEntity) {
        console.warn(`通过 ViewerManager 添加卫星覆盖范围 ID 为 "${coverageEntity.id}" 的实体失败。`);
      }
    }

    let addedOrbitEntity: Cesium.Entity | null = null;
    if (orbitEntity) {
      addedOrbitEntity = this.viewerManager.addEntity(orbitEntity);
      if (!addedOrbitEntity) {
        console.warn(`通过 ViewerManager 添加卫星轨道 ID 为 "${orbitEntity.id}" 的实体失败。`);
      }
    }
    // --- 添加结束 ---

    // 存储实体引用
    this.currentSatelliteEntities.set(id, {
      mainEntity: addedMainEntity, // 存储实际添加成功的实体
      orbitEntity: addedOrbitEntity ?? undefined,
      coverageEntity: addedCoverageEntity ?? undefined,
    });
  }

  /**
   * 创建卫星主体实体。
   */
  private _createSatelliteEntity(
    id: string,
    name: string,
    sampledPositionProperty: Cesium.SampledPositionProperty,
    randomBaseColor: Cesium.Color,
    options: I卫星,
  ): Cesium.Entity {
    // 动态轨迹路径 (Path) - 注意：这与完整轨道线 (Polyline) 不同
    const path: Cesium.PathGraphics.ConstructorOptions = {
      resolution: 1,
      material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.15,
        color: randomBaseColor,
      }),
      width: 2,
      leadTime: (options.orbitDurationSeconds ?? 3600 * 2) / 2, // 默认1小时
      trailTime: (options.orbitDurationSeconds ?? 3600 * 2) / 2, // 默认1小时
    };

    return new Cesium.Entity({
      id,
      name,
      path: options.showPath ? path : undefined, // 根据 options.showPath 控制是否显示路径
      position: sampledPositionProperty, // 使用计算好的位置属性
      orientation: new Cesium.VelocityOrientationProperty(sampledPositionProperty),
      point: {
        pixelSize: 8,
        color: randomBaseColor,
        outlineColor: Cesium.Color.WHITE,
        outlineWidth: 1,
      },
      label: {
        text: name,
        font: '14pt sans-serif',
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(0, -10),
        fillColor: Cesium.Color.WHITE,
        outlineColor: Cesium.Color.BLACK,
      },
    });
  }

  /**
   * 创建卫星覆盖范围实体。
   */
  private _createCoverageEntity(
    satelliteId: string,
    satelliteName: string,
    positionProperty: Cesium.SampledPositionProperty,
    baseColor: Cesium.Color,
  ): Cesium.Entity | null {
    // 使用 CallbackProperty 动态计算星下点位置
    const subsatellitePosition = new Cesium.CallbackPositionProperty( // 使用 CallbackPositionProperty
      (time, result) => {
        const satelliteCartesian = positionProperty.getValue(time, result);
        if (!satelliteCartesian) return;
        const satelliteCartographic = Cesium.Cartographic.fromCartesian(satelliteCartesian);
        if (!satelliteCartographic) return;
        const subsatelliteCartographic = new Cesium.Cartographic(
          satelliteCartographic.longitude,
          satelliteCartographic.latitude,
          0,
        );
        return Cesium.Cartographic.toCartesian(subsatelliteCartographic, Cesium.Ellipsoid.WGS84, result);
      },
      false,
      Cesium.ReferenceFrame.FIXED,
    );

    // 使用 CallbackProperty 动态计算覆盖半径 (基于高度的简单估算)
    const coverageRadius = new Cesium.CallbackProperty((time) => {
      const satelliteCartesian = positionProperty.getValue(time);
      if (!satelliteCartesian) return 100_000; // 默认半径
      const satelliteCartographic = Cesium.Cartographic.fromCartesian(satelliteCartesian);
      if (!satelliteCartographic) return 100_000;
      const altitude = satelliteCartographic.height;
      // 简化的估算
      const calculatedRadius = altitude * 0.8;
      return Math.max(calculatedRadius, 50_000); // 最小半径 50km
    }, false);

    return new Cesium.Entity({
      id: `${satelliteId}-coverage`,
      name: `${satelliteName} 覆盖范围`,
      position: subsatellitePosition,
      ellipse: {
        semiMajorAxis: coverageRadius,
        semiMinorAxis: coverageRadius,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        granularity: Cesium.Math.toRadians(1),

        outlineWidth: 1,
        material: baseColor.withAlpha(0.2),
        outline: true,
        outlineColor: baseColor.withAlpha(0.8),
      },
    });
  }

  /**
   * 创建卫星轨道实体。
   */
  private _createOrbitEntity(
    satelliteId: string,
    satelliteName: string,
    orbitPositions: Cesium.Cartesian3[],
    baseColor: Cesium.Color,
  ): Cesium.Entity {
    return new Cesium.Entity({
      id: `${satelliteId}-orbit`,
      name: `${satelliteName} 轨道`,
      polyline: {
        positions: orbitPositions,
        width: 1,
        material: new Cesium.PolylineDashMaterialProperty({
          color: baseColor.withAlpha(0.5),
          dashLength: 16,
        }),
        clampToGround: false, // 轨道通常不贴地
      },
    });
  }

  /**
   * 从视图中移除指定的卫星实体及其相关元素 (通过 ID)。
   * @param entityId - 要移除的卫星实体的 ID。
   * @returns 如果成功移除所有相关实体则返回 true，否则返回 false。
   */
  removeSatellite(entityId: string): boolean {
    const satelliteData = this.currentSatelliteEntities.get(entityId);
    if (!satelliteData) {
      // console.warn(`未在 SatelliteManager 中找到 ID 为 "${entityId}" 的实体，无法移除。`);
      return false; // 不在管理范围内
    }

    let allRemoved = true;

    // 移除主体
    if (!this.viewerManager.removeEntity(satelliteData.mainEntity)) {
      console.warn(`尝试通过 ViewerManager 移除卫星主体 ID 为 "${entityId}" 的实体失败。`);
      allRemoved = false;
    }

    // 移除轨道
    if (satelliteData.orbitEntity && !this.viewerManager.removeEntity(satelliteData.orbitEntity)) {
      console.warn(`尝试通过 ViewerManager 移除卫星轨道 ID 为 "${satelliteData.orbitEntity.id}" 的实体失败。`);
      allRemoved = false;
    }

    // 移除覆盖范围
    if (satelliteData.coverageEntity && !this.viewerManager.removeEntity(satelliteData.coverageEntity)) {
      console.warn(`尝试通过 ViewerManager 移除卫星覆盖范围 ID 为 "${satelliteData.coverageEntity.id}" 的实体失败。`);
      allRemoved = false;
    }

    // 从 Map 中删除，无论移除是否完全成功，以避免状态不一致
    this.currentSatelliteEntities.delete(entityId);

    return allRemoved;
  }

  /**
   * 清除所有由此管理器管理的卫星实体及其相关元素。
   */
  clearAllSatellites(): void {
    const idsToRemove = [...this.currentSatelliteEntities.keys()];
    let removalFailed = false;
    for (const id of idsToRemove) {
      if (!this.removeSatellite(id)) {
        removalFailed = true;
      }
    }
    if (removalFailed) {
      console.warn('清除部分卫星实体时遇到问题。');
    }
    // 确保最终清空 Map
    this.currentSatelliteEntities.clear();
  }

  /**
   * 获取当前管理的卫星实体 Map。
   * @returns 返回包含当前卫星实体及其关联实体的 Map。
   */
  getCurrentSatelliteEntities(): Map<string, ManagedSatelliteEntities> {
    return this.currentSatelliteEntities;
  }

  /**
   * 销毁管理器，清理资源。
   */
  destroy(): void {
    this.clearAllSatellites();
    // console.log('SatelliteManager 已销毁。');
  }
}
