import * as THREE from 'three';
import { createNoise3D } from 'simplex-noise';

import { CONFIG, CABLE_CONFIG, CABLE_STATE } from './constants.js';
import { latLonToVector3, vector3ToLatLon, screenToEarthCoords } from './utils.js';
import { 
  showStatusMessage, 
  updateCoordinatesDisplay, 
  updateZoomDisplay, 
  updateEarthStats,
  setLoading,
  showTooltip,
  hideTooltip 
} from './ui.js';
import { createEarth, createClouds, createTerrain, createStars, createGridLines, toggleTerrain, getEarth } from './earth.js';
import { loadGeoJSONFromPath, loadLandingPoints, handleCableClick, clearCableSelection, getCableLines, getCablesById, lockedCable as cableLocked, getCableState, setCableState, clearAllCableStates, applyLandingPointVisualState, resetLandingPointVisualState, getAllLandingPoints, getShowCables } from './cables.js';
import { createSatellites, loadSatellites, updateSatellitePositions, toggleSatellites, toggleTrails, getShowSatellites, getSatelliteCount, selectSatellite, getSatelliteData, getSatellitePoints, setSatelliteRingState, updateLockedRingPosition, updateHoverRingPosition, getSatellitePositions, showPredictedOrbit, hidePredictedOrbit, updateBreathingPhase } from './satellites.js';
import { setupControls, getAutoRotate, getShowTerrain, zoomLevel, setAutoRotate, toggleAutoRotate, resetView } from './controls.js';
import { initInfoCard, showInfoCard, hideInfoCard, getCurrentType, setInfoCardNoBorder } from './info-card.js';

export let scene, camera, renderer;
let simplex;
let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
let hoveredCable = null;
let hoveredSatellite = null;
let hoveredSatelliteIndex = null;
let cableLockedData = null;
let lockedSatellite = null;
let lockedSatelliteIndex = null;
let lockedObject = null;
let lockedObjectType = null;
let dragStartTime = 0;
let isLongDrag = false;
let lastSatClickTime = 0;
let lastSatClickIndex = 0;
let lastSatClickPos = { x: 0, y: 0 };

export function clearLockedObject() {
  hidePredictedOrbit();
  hoveredCable = null;
  hoveredSatellite = null;
  hoveredSatelliteIndex = null;
  clearAllCableStates();
  setSatelliteRingState(null, 'none', null);
  lockedObject = null;
  lockedObjectType = null;
  lockedSatellite = null;
  lockedSatelliteIndex = null;
  window.lockedSatelliteIndex = null;
  cableLockedData = null;
}

function isSameCable(cable1, cable2) {
  if (!cable1 || !cable2) return false;
  const id1 = cable1.userData?.cableId;
  const id2 = cable2.userData?.cableId;
  if (id1 === undefined || id2 === undefined) return false;
  return id1 === id2;
}

function showCableInfo(cable) {
  showInfoCard('cable', {
    name: cable.userData.name,
    owner: cable.userData.owner,
    status: cable.userData.status,
    length: cable.userData.length,
    coords: cable.userData.coords,
    rfs: cable.userData.rfs
  });
}

function showSatelliteInfo(props) {
  const meanMotion = props?.mean_motion || 0;
  const period = meanMotion > 0 ? (1440 / meanMotion).toFixed(1) : '-';
  const ecc = props?.eccentricity || 0;
  const perigee = (6371 * (1 - ecc)).toFixed(0);
  const apogee = (6371 * (1 + ecc)).toFixed(0);
  
  showInfoCard('satellite', {
    name: props?.name || '-',
    norad_id: props?.norad_cat_id,
    inclination: props?.inclination ? props.inclination.toFixed(2) : '-',
    period: period,
    perigee: perigee,
    apogee: apogee
  });
}

function applyCableVisualState() {
  const allCables = getCableLines();
  const pulse = (Math.sin(Date.now() * CABLE_CONFIG.pulseSpeed) + 1) * 0.5;
  
  allCables.forEach(c => {
    const cableId = c.userData.cableId;
    const state = getCableState(cableId);
    
    switch (state) {
      case CABLE_STATE.LOCKED:
        c.material.opacity = CABLE_CONFIG.lockedOpacityMin + pulse * (CABLE_CONFIG.lockedOpacityMax - CABLE_CONFIG.lockedOpacityMin);
        c.material.color.setRGB(1, 1, 1);
        break;
      case CABLE_STATE.HOVERED:
        c.material.opacity = 1;
        c.material.color.setRGB(1, 1, 1);
        break;
      case CABLE_STATE.NORMAL:
      default:
        if ((lockedObjectType === 'cable' && lockedObject) || (lockedObjectType === 'satellite' && lockedSatellite)) {
          c.material.opacity = CABLE_CONFIG.otherOpacity;
          const origColor = c.userData.originalColor;
          const brightness = CABLE_CONFIG.otherBrightness;
          c.material.color.setRGB(
            ((origColor >> 16) & 255) / 255 * brightness,
            ((origColor >> 8) & 255) / 255 * brightness,
            (origColor & 255) / 255 * brightness
          );
        } else {
          c.material.opacity = 1;
          c.material.color.setHex(c.userData.originalColor);
        }
    }
  });
}

window.addEventListener('error', (e) => {
  console.error('全局错误:', e.error);
  showStatusMessage('加载错误: ' + e.error?.message, 'error');
});

window.addEventListener('unhandledrejection', (e) => {
  console.error('未处理的Promise错误:', e.reason);
});

export function init() {
  simplex = createNoise3D();
  
  scene = new THREE.Scene();
  
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.z = CONFIG.defaultCameraZ;
  window.camera = camera;
  
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false, powerPreference: 'high-performance' });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setClearColor(0x0a0a1a, 1);
  renderer.setPixelRatio(window.devicePixelRatio);
  document.getElementById('container').appendChild(renderer.domElement);
  
  addLights();
  initInfoCard();
  const earthObj = createEarth(scene);
  createClouds(scene, earthObj);
  createTerrain(scene, earthObj, simplex);
  createStars(scene);
  createGridLines(scene, earthObj);
  createSatellites(scene, earthObj);
  
  setupControls(camera, renderer, scene, earthObj);
  resetView(camera);
  setupEventListeners(camera, renderer);
  
  loadData();
  
  animate();
}

function addLights() {
  const ambientLight = new THREE.AmbientLight(0x404060);
  scene.add(ambientLight);
  
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
  directionalLight.position.set(5, 3, 5);
  scene.add(directionalLight);
  
  const backLight = new THREE.DirectionalLight(0x446688, 0.3);
  backLight.position.set(-5, 0, -5);
  scene.add(backLight);
  
  const pointLight = new THREE.PointLight(0xffffff, 0.4);
  pointLight.position.set(10, 10, 10);
  scene.add(pointLight);
}

let earthTexture = null;

async function loadData(showWhiteSphere = false) {
  if (showWhiteSphere) {
    const earth = getEarth();
    if (earth && earth.material) {
      earthTexture = earth.material.map;
      earth.material.map = null;
      earth.material.color.setHex(0xffffff);
      earth.material.needsUpdate = true;
    }
  }
  
  setLoading(true);
  try {
    console.log('开始加载数据...');
    await Promise.all([
      (async () => {
        await loadGeoJSONFromPath(scene, getEarth());
        console.log('电缆数据加载完成');
        await loadLandingPoints(scene, getEarth());
        console.log('登陆点数据加载完成');
      })(),
      (async () => {
        const satCount = await loadSatellites();
        console.log(`卫星数据加载完成: ${satCount} 颗`);
        document.getElementById('satellite-count').textContent = satCount + ' 颗';
        updateSatellitePositions();
        console.log('卫星位置已更新');
        toggleSatellites(true);
        const satBtn = document.getElementById('toggle-satellites');
        if (satBtn) {
          satBtn.classList.add('active');
          satBtn.querySelector('.tooltip').textContent = '隐藏卫星';
        }
      })()
    ]);
  } catch (error) {
    console.error('加载数据失败:', error);
    showStatusMessage('加载数据失败: ' + error.message, 'error');
  }
  setLoading(false);
  
  if (showWhiteSphere) {
    const earth = getEarth();
    if (earth && earth.material) {
      earth.material.map = earthTexture;
      earth.material.color.setHex(0xffffff);
      earth.material.needsUpdate = true;
    }
  }
}

export async function reloadData() {
  await loadData(true);
}

function setupEventListeners(camera, renderer) {
  window.addEventListener('resize', () => onWindowResize(camera, renderer));
  
  renderer.domElement.addEventListener('mousemove', (e) => onMouseMove(e, camera));
  renderer.domElement.addEventListener('mousedown', onMouseDown);
  renderer.domElement.addEventListener('mouseup', onMouseUp);
  renderer.domElement.addEventListener('click', (e) => onClick(e, camera, renderer));
}

function onWindowResize(camera, renderer) {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

function getFrontFacingCables(cableLines, camera) {
  const earth = getEarth();
  if (!earth) return cableLines;
  
  const cameraDir = new THREE.Vector3();
  camera.getWorldDirection(cameraDir);
  
  return cableLines.filter(cable => {
    const cablePos = new THREE.Vector3();
    cable.geometry.computeBoundingBox();
    const boundingBox = cable.geometry.boundingBox;
    if (boundingBox) {
      boundingBox.getCenter(cablePos);
      cable.localToWorld(cablePos);
    }
    
    const toCamera = new THREE.Vector3().subVectors(camera.position, earth.position).normalize();
    const toCable = new THREE.Vector3().subVectors(cablePos, earth.position).normalize();
    
    return toCamera.dot(toCable) > 0;
  });
}

function onMouseMove(event, camera) {
  const earth = getEarth();
  if (!earth) return;
  
  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2(
    (event.clientX / window.innerWidth) * 2 - 1,
    -(event.clientY / window.innerHeight) * 2 + 1
  );
  
  raycaster.setFromCamera(mouse, camera);
  
  const allCableLines = getCableLines();
  const frontCables = getFrontFacingCables(allCableLines, camera);
  const intersects = raycaster.intersectObjects(frontCables);
  
  const hasHoveredCable = intersects.length > 0;
  let hoveredSat = null;
  let hoveredSatIndexFromIntersect = null;
  if (getShowSatellites()) {
    const satPoints = getSatellitePoints();
    if (satPoints) {
      const satIntersects = raycaster.intersectObject(satPoints);
      if (satIntersects.length > 0) {
        hoveredSatIndexFromIntersect = satIntersects[0].index;
        hoveredSat = selectSatellite(hoveredSatIndexFromIntersect);
      }
    }
  }
  const hasHoveredSatellite = hoveredSat && hoveredSat.properties;
  
  if (hoveredCable) {
    if (!hasHoveredCable || !isSameCable(intersects[0]?.object, hoveredCable)) {
      if (!isSameCable(hoveredCable, lockedObject)) {
        setCableState(hoveredCable.userData.cableId, CABLE_STATE.NORMAL);
      }
      hoveredCable = null;
    }
  }
  
  if (hoveredSatelliteIndex !== null && hoveredSatelliteIndex !== hoveredSatIndexFromIntersect) {
    if (hoveredSatelliteIndex !== lockedSatelliteIndex) {
      setSatelliteRingState(hoveredSatelliteIndex, 'none', null);
    }
    hoveredSatelliteIndex = null;
  }
  
  if (hasHoveredCable && getShowCables()) {
    const cable = intersects[0].object;
    if (!isSameCable(cable, lockedObject)) {
      hoveredCable = cable;
      setCableState(cable.userData.cableId, CABLE_STATE.HOVERED);
    } else {
      hoveredCable = cable;
    }
    
    showCableInfo(cable);
    setInfoCardNoBorder(true);
    hideTooltip();
  } else if (hasHoveredSatellite) {
    hoveredSatellite = hoveredSat;
    hoveredSatelliteIndex = hoveredSatIndexFromIntersect;
    if (hoveredSatelliteIndex !== lockedSatelliteIndex) {
      const satPositions = getSatellitePositions();
      if (satPositions && satPositions[hoveredSatelliteIndex]) {
        setSatelliteRingState(hoveredSatelliteIndex, 'hover', satPositions[hoveredSatelliteIndex].current);
      }
    }
    showSatelliteInfo(hoveredSat.properties);
    setInfoCardNoBorder(true);
  } else if (lockedObjectType === 'cable' && lockedObject) {
    showCableInfo(lockedObject);
  } else if (lockedObjectType === 'satellite' && lockedSatellite) {
    if (lockedSatelliteIndex !== null && lockedSatelliteIndex !== undefined) {
      const satPositions = getSatellitePositions();
      if (satPositions && satPositions[lockedSatelliteIndex]) {
        setSatelliteRingState(lockedSatelliteIndex, 'locked', satPositions[lockedSatelliteIndex].current);
      }
    }
    showSatelliteInfo(lockedSatellite.properties);
  } else {
    hideInfoCard();
  }
  
  const earthPoint = screenToEarthCoords(event.clientX, event.clientY, camera, earth);
  if (earthPoint) {
    const coords = vector3ToLatLon(earthPoint);
    updateCoordinatesDisplay(coords.lat, coords.lon, coords.alt);
    
    if (!isDragging) {
      showTooltip(event.clientX + 10, event.clientY + 10, 
        `纬度: ${coords.lat}°<br>经度: ${coords.lon}°<br>海拔: ${coords.alt.toFixed(1)} km`);
    }
  } else {
    hideTooltip();
  }
  
  if (isDragging) {
    if (Date.now() - dragStartTime > 500) {
      isLongDrag = true;
    }
    
    const deltaX = event.clientX - previousMousePosition.x;
    const deltaY = event.clientY - previousMousePosition.y;
    
    earth.rotation.y += deltaX * 0.005;
    earth.rotation.x += deltaY * 0.005;
    
    previousMousePosition = { x: event.clientX, y: event.clientY };
  }
}

function onMouseDown(event) {
  isDragging = true;
  dragStartTime = Date.now();
  isLongDrag = false;
  previousMousePosition = { x: event.clientX, y: event.clientY };
  document.getElementById('container').classList.add('dragging');
  hideTooltip();
}

function onMouseUp() {
  isDragging = false;
  document.getElementById('container').classList.remove('dragging');
}

function onClick(event, camera, renderer) {
  const earth = getEarth();
  if (!earth) return;
  
  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2(
    (event.clientX / window.innerWidth) * 2 - 1,
    -(event.clientY / window.innerHeight) * 2 + 1
  );
  
  raycaster.setFromCamera(mouse, camera);
  
  const allCableLines = getCableLines();
  const frontCables = getFrontFacingCables(allCableLines, camera);
  const intersects = raycaster.intersectObjects(frontCables);
  const satIntersects = getShowSatellites() ? raycaster.intersectObject(getSatellitePoints()) : [];
  
  if (intersects.length > 0 && getShowCables()) {
    clearLockedObject();
    
    const clickedCable = intersects[0].object;
    const cableId = clickedCable.userData.cableId;
    
    setCableState(cableId, CABLE_STATE.LOCKED);
    
    lockedObject = clickedCable;
    lockedObjectType = 'cable';
    cableLockedData = { ...clickedCable.userData };
    
    setAutoRotate(false);
    handleCableClick(clickedCable);
  } else if (satIntersects.length > 0) {
    const now = Date.now();
    const clickX = event.clientX;
    const clickY = event.clientY;
    
    let selectedIndex;
    if (satIntersects.length > 1 && 
        now - lastSatClickTime < 500 &&
        Math.abs(clickX - lastSatClickPos.x) < 30 &&
        Math.abs(clickY - lastSatClickPos.y) < 30) {
      const currentIdx = satIntersects.findIndex(s => s.index === lastSatClickIndex);
      selectedIndex = satIntersects[(currentIdx + 1) % satIntersects.length].index;
    } else {
      selectedIndex = satIntersects[0].index;
    }
    
    lastSatClickTime = now;
    lastSatClickIndex = selectedIndex;
    lastSatClickPos = { x: clickX, y: clickY };
    
    const sat = selectSatellite(selectedIndex);
    
    if (sat && sat.properties) {
      clearLockedObject();
      
      lockedObject = sat;
      lockedObjectType = 'satellite';
      lockedSatellite = sat;
      lockedSatelliteIndex = selectedIndex;
      window.lockedSatelliteIndex = selectedIndex;
      showPredictedOrbit(sat);
      setAutoRotate(false);
      
      const satPositions = getSatellitePositions();
      if (satPositions && satPositions[selectedIndex]) {
        setSatelliteRingState(selectedIndex, 'locked', satPositions[selectedIndex].current);
      }
      
      const props = sat.properties;
      
      const meanMotion = props.mean_motion || 0;
      const period = meanMotion > 0 ? (1440 / meanMotion).toFixed(1) : '-';
      
      const ecc = props.eccentricity || 0;
      const earthRadius = 6371;
      const perigee = (earthRadius * (1 - ecc)).toFixed(0);
      const apogee = (earthRadius * (1 + ecc)).toFixed(0);
      
      showInfoCard('satellite', {
        name: props.name,
        norad_id: props.norad_cat_id,
        inclination: props.inclination ? props.inclination.toFixed(2) : '-',
        period: period,
        perigee: perigee,
        apogee: apogee
      });
      
      showStatusMessage('已选择: ' + props.name, 'info');
    }
  } else {
    if (!isLongDrag) {
      clearLockedObject();
      setAutoRotate(true);
      clearCableSelection();
    }
  }
}

function animate() {
  requestAnimationFrame(animate);
  
  const earth = getEarth();
  
  if (getAutoRotate() && earth) {
    earth.rotation.y += CONFIG.rotationSpeed;
  }
  
  applyCableVisualState();
  
  if (lockedObjectType === 'cable' && lockedObject) {
    applyLandingPointVisualState(lockedObject.userData.name, false);
  } else if (lockedObjectType === 'satellite' && lockedSatellite) {
    applyLandingPointVisualState(null, true);
  } else {
    resetLandingPointVisualState();
  }
  
  updateSatellitePositions(16);
  
  const satPositions = getSatellitePositions();
  
  // 更新呼吸动画相位
  updateBreathingPhase();

  if (lockedObjectType === 'satellite' && lockedSatelliteIndex !== null) {
    if (satPositions && satPositions[lockedSatelliteIndex]) {
      updateLockedRingPosition(satPositions[lockedSatelliteIndex].current);
    }
  } else if (hoveredSatelliteIndex !== null && satPositions && satPositions[hoveredSatelliteIndex]) {
    updateHoverRingPosition(satPositions[hoveredSatelliteIndex].current);
  }
  
  renderer.render(scene, camera);
}

window.clearLockedCable = function() {
  clearLockedObject();
};

window.clearSelection = function() {
  hideInfoCard();
  window.clearLockedCable();
};

document.addEventListener('DOMContentLoaded', init);
