/**
 * Portfolio Hero - 3D Network Globe
 * Stunning globe with glowing network connections
 */

import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js';

class HeroScene {
    constructor() {
        this.container = document.getElementById('hero3d');
        if (!this.container) return;

        this.width = this.container.clientWidth;
        this.height = this.container.clientHeight;
        this.mouse = { x: 0, y: 0 };
        this.time = 0;

        this.init();
        this.createGlobe();
        this.createNetworkLines();
        this.createDataPoints();
        this.createStars();
        this.addLights();
        this.animate();
        this.addEventListeners();
    }

    init() {
        this.scene = new THREE.Scene();

        this.camera = new THREE.PerspectiveCamera(60, this.width / this.height, 0.1, 1000);
        this.camera.position.z = 4;

        this.renderer = new THREE.WebGLRenderer({
            alpha: true,
            antialias: true
        });
        this.renderer.setSize(this.width, this.height);
        this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
        this.renderer.setClearColor(0x000000, 0);
        this.container.appendChild(this.renderer.domElement);

        // Main group
        this.globeGroup = new THREE.Group();
        this.scene.add(this.globeGroup);
    }

    createGlobe() {
        // Main sphere - wireframe style
        const sphereGeometry = new THREE.SphereGeometry(1.5, 64, 64);

        // Inner glow sphere
        const innerMaterial = new THREE.MeshPhysicalMaterial({
            color: 0x0a0a1f,
            metalness: 0.3,
            roughness: 0.7,
            transparent: true,
            opacity: 0.9
        });
        this.innerSphere = new THREE.Mesh(sphereGeometry, innerMaterial);
        this.globeGroup.add(this.innerSphere);

        // Outer wireframe
        const wireframeMaterial = new THREE.MeshBasicMaterial({
            color: 0x8B5CF6,
            wireframe: true,
            transparent: true,
            opacity: 0.15
        });
        this.wireframeSphere = new THREE.Mesh(sphereGeometry.clone(), wireframeMaterial);
        this.wireframeSphere.scale.set(1.01, 1.01, 1.01);
        this.globeGroup.add(this.wireframeSphere);

        // Glowing outer ring (equator)
        const ringGeometry = new THREE.TorusGeometry(1.55, 0.02, 16, 100);
        const ringMaterial = new THREE.MeshBasicMaterial({
            color: 0x06B6D4,
            transparent: true,
            opacity: 0.6
        });
        this.equatorRing = new THREE.Mesh(ringGeometry, ringMaterial);
        this.equatorRing.rotation.x = Math.PI / 2;
        this.globeGroup.add(this.equatorRing);

        // Second orbit ring
        const ring2 = new THREE.Mesh(ringGeometry.clone(), new THREE.MeshBasicMaterial({
            color: 0xF472B6,
            transparent: true,
            opacity: 0.4
        }));
        ring2.rotation.x = Math.PI / 3;
        ring2.rotation.y = Math.PI / 4;
        ring2.scale.set(1.1, 1.1, 1.1);
        this.orbitRing = ring2;
        this.globeGroup.add(ring2);

        // Third orbit ring
        const ring3 = new THREE.Mesh(ringGeometry.clone(), new THREE.MeshBasicMaterial({
            color: 0x34D399,
            transparent: true,
            opacity: 0.3
        }));
        ring3.rotation.x = -Math.PI / 4;
        ring3.rotation.z = Math.PI / 3;
        ring3.scale.set(1.2, 1.2, 1.2);
        this.orbitRing2 = ring3;
        this.globeGroup.add(ring3);
    }

    createNetworkLines() {
        this.networkLines = [];
        const lineCount = 20;

        for (let i = 0; i < lineCount; i++) {
            // Random start point on sphere
            const phi1 = Math.random() * Math.PI * 2;
            const theta1 = Math.acos((Math.random() * 2) - 1);
            const start = new THREE.Vector3(
                1.52 * Math.sin(theta1) * Math.cos(phi1),
                1.52 * Math.sin(theta1) * Math.sin(phi1),
                1.52 * Math.cos(theta1)
            );

            // Random end point on sphere
            const phi2 = Math.random() * Math.PI * 2;
            const theta2 = Math.acos((Math.random() * 2) - 1);
            const end = new THREE.Vector3(
                1.52 * Math.sin(theta2) * Math.cos(phi2),
                1.52 * Math.sin(theta2) * Math.sin(phi2),
                1.52 * Math.cos(theta2)
            );

            // Create curved line (arc)
            const mid = new THREE.Vector3().addVectors(start, end).multiplyScalar(0.5);
            mid.normalize().multiplyScalar(2.2); // Curve outward

            const curve = new THREE.QuadraticBezierCurve3(start, mid, end);
            const points = curve.getPoints(50);
            const geometry = new THREE.BufferGeometry().setFromPoints(points);

            // Gradient color line
            const colors = [0x8B5CF6, 0x06B6D4, 0xF472B6, 0x34D399];
            const material = new THREE.LineBasicMaterial({
                color: colors[i % colors.length],
                transparent: true,
                opacity: 0.6
            });

            const line = new THREE.Line(geometry, material);
            line.userData = {
                startOpacity: Math.random() * 0.5 + 0.3,
                pulseSpeed: Math.random() * 2 + 1,
                pulseOffset: Math.random() * Math.PI * 2
            };

            this.networkLines.push(line);
            this.globeGroup.add(line);
        }
    }

    createDataPoints() {
        this.dataPoints = [];
        const pointCount = 30;

        const pointGeometry = new THREE.SphereGeometry(0.03, 8, 8);
        const colors = [0x8B5CF6, 0x06B6D4, 0xF472B6, 0x34D399];

        for (let i = 0; i < pointCount; i++) {
            const phi = Math.random() * Math.PI * 2;
            const theta = Math.acos((Math.random() * 2) - 1);

            const material = new THREE.MeshBasicMaterial({
                color: colors[i % colors.length],
                transparent: true,
                opacity: 0.9
            });

            const point = new THREE.Mesh(pointGeometry, material);
            point.position.set(
                1.52 * Math.sin(theta) * Math.cos(phi),
                1.52 * Math.sin(theta) * Math.sin(phi),
                1.52 * Math.cos(theta)
            );

            point.userData = {
                pulseSpeed: Math.random() * 3 + 1,
                pulseOffset: Math.random() * Math.PI * 2,
                baseScale: 0.8 + Math.random() * 0.4
            };

            this.dataPoints.push(point);
            this.globeGroup.add(point);
        }

        // Add larger glowing nodes at key points
        const nodeGeometry = new THREE.SphereGeometry(0.06, 16, 16);
        const nodeMaterial = new THREE.MeshPhysicalMaterial({
            color: 0x8B5CF6,
            emissive: 0x8B5CF6,
            emissiveIntensity: 0.5,
            transparent: true,
            opacity: 0.9
        });

        for (let i = 0; i < 6; i++) {
            const phi = (i / 6) * Math.PI * 2;
            const theta = Math.PI / 2 + (Math.random() - 0.5) * 0.5;

            const node = new THREE.Mesh(nodeGeometry, nodeMaterial.clone());
            node.position.set(
                1.55 * Math.sin(theta) * Math.cos(phi),
                1.55 * Math.sin(theta) * Math.sin(phi),
                1.55 * Math.cos(theta)
            );

            node.userData = {
                pulseSpeed: 2,
                pulseOffset: i * 0.5,
                baseScale: 1
            };

            this.dataPoints.push(node);
            this.globeGroup.add(node);
        }
    }

    createStars() {
        const starGeometry = new THREE.BufferGeometry();
        const starCount = 200;
        const positions = new Float32Array(starCount * 3);

        for (let i = 0; i < starCount; i++) {
            positions[i * 3] = (Math.random() - 0.5) * 20;
            positions[i * 3 + 1] = (Math.random() - 0.5) * 20;
            positions[i * 3 + 2] = (Math.random() - 0.5) * 20 - 5;
        }

        starGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));

        const starMaterial = new THREE.PointsMaterial({
            color: 0xffffff,
            size: 0.03,
            transparent: true,
            opacity: 0.6
        });

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

    addLights() {
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
        this.scene.add(ambientLight);

        const pointLight1 = new THREE.PointLight(0x8B5CF6, 1.5, 10);
        pointLight1.position.set(3, 2, 3);
        this.scene.add(pointLight1);

        const pointLight2 = new THREE.PointLight(0x06B6D4, 1, 8);
        pointLight2.position.set(-3, -2, 2);
        this.scene.add(pointLight2);

        const pointLight3 = new THREE.PointLight(0xF472B6, 0.8, 6);
        pointLight3.position.set(0, 3, -2);
        this.scene.add(pointLight3);
    }

    addEventListeners() {
        window.addEventListener('mousemove', (e) => {
            this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
            this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
        });

        window.addEventListener('resize', () => {
            this.width = this.container.clientWidth;
            this.height = this.container.clientHeight;
            this.camera.aspect = this.width / this.height;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(this.width, this.height);
        });
    }

    animate() {
        requestAnimationFrame(() => this.animate());

        this.time += 0.01;

        // Rotate globe slowly
        this.globeGroup.rotation.y += 0.003;

        // Mouse influence on rotation
        this.globeGroup.rotation.x += (this.mouse.y * 0.3 - this.globeGroup.rotation.x) * 0.02;

        // Orbit rings rotation
        this.orbitRing.rotation.z += 0.005;
        this.orbitRing2.rotation.y += 0.003;

        // Pulse network lines
        this.networkLines.forEach((line) => {
            const data = line.userData;
            const pulse = Math.sin(this.time * data.pulseSpeed + data.pulseOffset) * 0.3 + 0.5;
            line.material.opacity = data.startOpacity * pulse;
        });

        // Pulse data points
        this.dataPoints.forEach((point) => {
            const data = point.userData;
            const pulse = Math.sin(this.time * data.pulseSpeed + data.pulseOffset) * 0.3 + 1;
            point.scale.setScalar(data.baseScale * pulse);
        });

        // Subtle star twinkle
        this.stars.material.opacity = 0.5 + Math.sin(this.time * 0.5) * 0.1;

        // Camera follows mouse slightly
        this.camera.position.x += (this.mouse.x * 0.5 - this.camera.position.x) * 0.02;
        this.camera.position.y += (this.mouse.y * 0.3 - this.camera.position.y) * 0.02;
        this.camera.lookAt(0, 0, 0);

        this.renderer.render(this.scene, this.camera);
    }
}

// Initialize
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => new HeroScene());
} else {
    new HeroScene();
}

export default HeroScene;
