import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

// Scene
const scene = new THREE.Scene();

// Camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 25, 45);
camera.lookAt(scene.position);

// Renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 10;
controls.maxDistance = 500;

// Lighting
const pointLight = new THREE.PointLight(0xffffff, 5, 3000); // Increased intensity and distance
scene.add(pointLight);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); // Increased ambient light
scene.add(ambientLight);


// Texture Loader
const textureLoader = new THREE.TextureLoader();

// Stars
const starVertices = [];
for (let i = 0; i < 10000; i++) {
    const x = (Math.random() - 0.5) * 2000;
    const y = (Math.random() - 0.5) * 2000;
    const z = (Math.random() - 0.5) * 2000;
    starVertices.push(x, y, z);
}

const starGeometry = new THREE.BufferGeometry();
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));

const starMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.7
});

const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);

// --- Sun ---
const sunTexture = textureLoader.load('assets/textures/sun.jpg');
const sunMaterial = new THREE.MeshBasicMaterial({ map: sunTexture });
const sun = new THREE.Mesh(new THREE.SphereGeometry(5, 32, 32), sunMaterial);
scene.add(sun);

// --- Planets & Orbits ---
const segments = 128;
const orbitMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, opacity: 0.5, transparent: true });

function createPlanet(radius, textureFile, distance, orbitSpeed) {
    const texture = textureLoader.load(`assets/textures/${textureFile}?v=${Date.now()}`);
    const geometry = new THREE.SphereGeometry(radius, 32, 32);
    const material = new THREE.MeshBasicMaterial({ map: texture }); // Reverted
    const planet = new THREE.Mesh(geometry, material);
    
    const pivot = new THREE.Object3D();
    sun.add(pivot);
    pivot.add(planet);
    planet.position.x = distance;

    // Trail setup
    const trailPoints = [];
    const trailGeometry = new THREE.BufferGeometry();
    const trailMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, opacity: 0.5, transparent: true });
    const trail = new THREE.Line(trailGeometry, trailMaterial);
    scene.add(trail);

    return { planet, pivot, orbitSpeed, trail, trailPoints };
}

const mercuryData = createPlanet(0.4, 'mercury.jpg', 7, 0.0297);
const venusData = createPlanet(0.9, 'venus.jpg', 11, 0.0116);
const earthData = createPlanet(1, 'earth.jpg', 15, 0.00717); // Adjusted for 365-day year
const marsData = createPlanet(0.7, 'mars.jpg', 20, 0.0038);
const jupiterData = createPlanet(3, 'jupiter.jpg', 30, 0.0006);
const saturnData = createPlanet(2.5, 'saturn.jpg', 40, 0.00024);
const uranusData = createPlanet(2, 'uranus.jpg', 50, 0.000085);
const neptuneData = createPlanet(1.9, 'neptune.jpg', 60, 0.000043);

// --- Saturn's Rings ---
const ringGeometry = new THREE.RingGeometry(3.5, 5, 64);
const ringMaterial = new THREE.MeshBasicMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide,
    transparent: true,
    opacity: 0.6
});
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.rotation.x = -Math.PI / 2.5; // Tilt the rings
saturnData.planet.add(ring);

// --- Moon ---
const moonGeometry = new THREE.SphereGeometry(0.25, 32, 32);
const moonMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
const moon = new THREE.Mesh(moonGeometry, moonMaterial);

const moonPivot = new THREE.Object3D();
earthData.planet.add(moonPivot);
moonPivot.add(moon);
moon.position.x = 2;


const planets = [mercuryData, venusData, earthData, marsData, jupiterData, saturnData, uranusData, neptuneData];

// Planet Data
const planetData = {
    [earthData.planet.uuid]: {
        name: 'Earth',
        mass: '5.97 × 10^24 kg',
        radius: '6,371 km',
        orbital_speed: '29.78 km/s',
    },
    [mercuryData.planet.uuid]: {
        name: 'Mercury',
        mass: '3.285 × 10^23 kg',
        radius: '2,439.7 km',
        orbital_speed: '47.36 km/s',
    },
    [venusData.planet.uuid]: {
        name: 'Venus',
        mass: '4.867 × 10^24 kg',
        radius: '6,051.8 km',
        orbital_speed: '35.02 km/s',
    },
    [marsData.planet.uuid]: {
        name: 'Mars',
        mass: '6.39 × 10^23 kg',
        radius: '3,389.5 km',
        orbital_speed: '24.07 km/s',
    },
    [jupiterData.planet.uuid]: {
        name: 'Jupiter',
        mass: '1.898 × 10^27 kg',
        radius: '69,911 km',
        orbital_speed: '13.07 km/s',
    },
    [saturnData.planet.uuid]: {
        name: 'Saturn',
        mass: '5.683 × 10^26 kg',
        radius: '58,232 km',
        orbital_speed: '9.69 km/s',
    },
    [uranusData.planet.uuid]: {
        name: 'Uranus',
        mass: '8.681 × 10^25 kg',
        radius: '25,362 km',
        orbital_speed: '6.81 km/s',
    },
    [neptuneData.planet.uuid]: {
        name: 'Neptune',
        mass: '1.024 × 10^26 kg',
        radius: '24,622 km',
        orbital_speed: '5.43 km/s',
    }
};

// --- Selection Outline ---
let outlineMesh;
const outlineMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.BackSide });
const outlineScale = 1.15;

function setOutline(object) {
    if (outlineMesh && outlineMesh.parent) {
        outlineMesh.parent.remove(outlineMesh);
    }

    outlineMesh = new THREE.Mesh(object.geometry, outlineMaterial);
    outlineMesh.scale.set(outlineScale, outlineScale, outlineScale);
    object.add(outlineMesh);
}


// Stats Panel
const statsInfo = document.getElementById('stats-info');
const statsButtons = document.getElementById('stats-buttons');

function updateStats(planetUUID) {
    const data = planetData[planetUUID];
    if (data) {
        statsInfo.innerHTML = `
            <h3>${data.name}</h3>
            <p>Mass: ${data.mass}</p>
            <p>Radius: ${data.radius}</p>
            <p>Orbital Speed: ${data.orbital_speed}</p>
        `;
    }
}

statsButtons.addEventListener('click', (event) => {
    if (event.target.tagName === 'BUTTON') {
        const planetName = event.target.dataset.planet;
        let planetObject, planetUUID;

        statsButtons.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
        event.target.classList.add('active');

        if (planetName === 'earth') {
            planetObject = earthData.planet;
            planetUUID = earthData.planet.uuid;
        } else if (planetName === 'mercury') {
            planetObject = mercuryData.planet;
            planetUUID = mercuryData.planet.uuid;
        } else if (planetName === 'venus') {
            planetObject = venusData.planet;
            planetUUID = venusData.planet.uuid;
        } else if (planetName === 'mars') {
            planetObject = marsData.planet;
            planetUUID = marsData.planet.uuid;
        } else if (planetName === 'jupiter') {
            planetObject = jupiterData.planet;
            planetUUID = jupiterData.planet.uuid;
        } else if (planetName === 'saturn') {
            planetObject = saturnData.planet;
            planetUUID = saturnData.planet.uuid;
        } else if (planetName === 'uranus') {
            planetObject = uranusData.planet;
            planetUUID = uranusData.planet.uuid;
        } else if (planetName === 'neptune') {
            planetObject = neptuneData.planet;
            planetUUID = neptuneData.planet.uuid;
        }

        if (planetUUID) {
            updateStats(planetUUID);
            if (planetObject) {
                setOutline(planetObject);
            }
        }
    }
});

// Display Earth's stats by default and set button to active
updateStats(earthData.planet.uuid);
statsButtons.querySelector('button[data-planet="earth"]').classList.add('active');
setOutline(earthData.planet); // Initial outline for Earth


// --- Controls Logic ---
let isPaused = false;
const pauseButton = document.getElementById('pause-button');
const speedToggleButton = document.getElementById('speed-toggle-button');

pauseButton.addEventListener('click', () => {
    isPaused = !isPaused;
    pauseButton.textContent = isPaused ? 'Play' : 'Pause';
});

const speeds = [1, 100, 500];
let currentSpeedIndex = 0;
let timeScale = speeds[currentSpeedIndex]; // Start with 1x speed

speedToggleButton.addEventListener('click', () => {
    currentSpeedIndex = (currentSpeedIndex + 1) % speeds.length;
    timeScale = speeds[currentSpeedIndex];
    speedToggleButton.textContent = 'Speed: ' + timeScale + 'x';
});


// --- Time & Simulation ---
const clock = new THREE.Clock();
const timeContainer = document.getElementById('time-container');
let simulationTime = new Date();
const ORBIT_SPEED_MULTIPLIER = 0.1;
const TIME_SPEED_FACTOR = 3600; // 1 real second = 1 simulation hour at 1x


function updateTimeDisplay() {
    const hours = String(simulationTime.getHours()).padStart(2, '0');
    const minutes = String(simulationTime.getMinutes()).padStart(2, '0');
    const seconds = String(simulationTime.getSeconds()).padStart(2, '0');
    const day = String(simulationTime.getDate()).padStart(2, '0');
    const month = String(simulationTime.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed
    const year = simulationTime.getFullYear();
    timeContainer.textContent = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

// Animation loop
function animate() {
    requestAnimationFrame(animate);

    // Get time delta for frame-rate independent animation
    const delta = clock.getDelta();

    // Update controls
    controls.update();

    if (!isPaused) {
        // Advance simulation time using milliseconds for precision
        const incrementMs = delta * 1000 * timeScale * TIME_SPEED_FACTOR;
        simulationTime.setTime(simulationTime.getTime() + incrementMs);

        // Sun's self-rotation (can be slower and independent of timeScale)
        sun.rotation.y += 0.005 * delta;
        
        const maxTrailPoints = 200;
        const worldPosition = new THREE.Vector3();

        planets.forEach(p => {
            // Orbit speed is now correctly scaled by timeScale
            p.pivot.rotation.y += p.orbitSpeed * ORBIT_SPEED_MULTIPLIER * delta * timeScale;
            
            // Planet's self-rotation (can also be constant)
            p.planet.rotation.y += 0.05 * delta;

            // Update trail
            p.planet.getWorldPosition(worldPosition);
            p.trailPoints.push(worldPosition.clone());

            if (p.trailPoints.length > maxTrailPoints) {
                p.trailPoints.shift();
            }

            p.trail.geometry.setFromPoints(p.trailPoints);
        });

        // Moon's orbit (also scaled by timeScale)
        moonPivot.rotation.y += 0.1 * ORBIT_SPEED_MULTIPLIER * delta * timeScale;
    }

    // Update time display every frame
    updateTimeDisplay();

    renderer.render(scene, camera);
}

animate();

// Handle window resize
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

// Initial call to set time
updateTimeDisplay();