import * as THREE from 'three';
import gsap from 'gsap';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';

// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.toneMapping = THREE.ReinhardToneMapping;
document.body.appendChild(renderer.domElement);

camera.position.z = 10;

// Post-processing
const renderScene = new RenderPass(scene, camera);
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
bloomPass.threshold = 0.2;
bloomPass.strength = 1.0;
bloomPass.radius = 0.5;

const composer = new EffectComposer(renderer);
composer.addPass(renderScene);
composer.addPass(bloomPass);

// Mouse Interaction
const mouse = new THREE.Vector2();
const targetMouse = new THREE.Vector2();
window.addEventListener('mousemove', (event) => {
    targetMouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    targetMouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});

// Circular Particle Texture
function createCircleTexture() {
    const canvas = document.createElement('canvas');
    canvas.width = 64;
    canvas.height = 64;
    const ctx = canvas.getContext('2d');
    const gradient = ctx.createRadialGradient(32, 32, 0, 32, 32, 32);
    gradient.addColorStop(0, 'rgba(255, 255, 255, 1)');
    gradient.addColorStop(0.2, 'rgba(255, 255, 255, 0.8)');
    gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.2)');
    gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 64, 64);
    return new THREE.CanvasTexture(canvas);
}
const particleTexture = createCircleTexture();

// Particles Variables
let particles;
const particleCount = 15000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const originalPositions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);

// Load Image and Sample Pixels
const loader = new THREE.TextureLoader();
loader.load('./logo.png', (texture) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = texture.image;

    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage(img, 0, 0);

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
    const sampledPixels = [];

    for (let i = 0; i < imageData.length; i += 4) {
        if (imageData[i + 3] > 128) {
            const index = i / 4;
            sampledPixels.push({
                x: ((index % canvas.width) - canvas.width / 2) / 20,
                y: (-(Math.floor(index / canvas.width)) + canvas.height / 2) / 20,
                r: imageData[i] / 255,
                g: imageData[i + 1] / 255,
                b: imageData[i + 2] / 255
            });
        }
    }

    for (let i = 0; i < particleCount; i++) {
        const pixel = sampledPixels[Math.floor(Math.random() * sampledPixels.length)];
        if (pixel) {
            positions[i * 3] = pixel.x + (Math.random() - 0.5) * 20;
            positions[i * 3 + 1] = pixel.y + (Math.random() - 0.5) * 20;
            positions[i * 3 + 2] = (Math.random() - 0.5) * 10;

            originalPositions[i * 3] = pixel.x;
            originalPositions[i * 3 + 1] = pixel.y;
            originalPositions[i * 3 + 2] = 0;

            colors[i * 3] = pixel.r;
            colors[i * 3 + 1] = pixel.g;
            colors[i * 3 + 2] = pixel.b;
        }
    }

    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));

    const material = new THREE.PointsMaterial({
        size: 0.1,
        map: particleTexture,
        vertexColors: true,
        transparent: true,
        depthWrite: false,
        blending: THREE.AdditiveBlending
    });

    particles = new THREE.Points(geometry, material);
    scene.add(particles);

    gsap.to(positions, {
        duration: 2.5,
        ease: "power4.inOut",
        onUpdate: () => {
            geometry.attributes.position.needsUpdate = true;
        }
    });
});

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

const clock = new THREE.Clock();
function animate() {
    requestAnimationFrame(animate);
    const time = clock.getElapsedTime();

    mouse.x += (targetMouse.x - mouse.x) * 0.1;
    mouse.y += (targetMouse.y - mouse.y) * 0.1;

    if (particles) {
        const posAttr = particles.geometry.attributes.position;
        for (let i = 0; i < particleCount; i++) {
            const ix = i * 3, iy = i * 3 + 1, iz = i * 3 + 2;
            const tx = originalPositions[ix], ty = originalPositions[iy], tz = originalPositions[iz];
            const dx = (mouse.x * 6) - tx, dy = (mouse.y * 6) - ty;
            const dist = Math.sqrt(dx * dx + dy * dy);
            const force = Math.max(0, (2.5 - dist) / 2.5);

            posAttr.array[ix] += (tx - posAttr.array[ix]) * 0.08 + (dx * force * 0.3);
            posAttr.array[iy] += (ty - posAttr.array[iy]) * 0.08 + (dy * force * 0.3);
            posAttr.array[iz] += (tz - posAttr.array[iz]) * 0.08 + (Math.sin(time + i * 0.1) * 0.02);
        }
        posAttr.needsUpdate = true;
        particles.rotation.y = mouse.x * 0.15;
    }

    composer.render();
}
animate();
