import React, { useMemo } from 'react';
import * as THREE from 'three';
import { createNoise2D } from 'simplex-noise';
import { getTerrainHeight } from './math';

export const Landscape: React.FC<{ seed: number }> = ({ seed }) => {
    const geometry = useMemo(() => {
        // Generate a very large plane with many segments
        const size = 1200;
        const segments = 128;
        const geo = new THREE.PlaneGeometry(size, size, segments, segments);
        geo.rotateX(-Math.PI / 2); // Lay flat on XZ plane

        const pos = geo.attributes.position;
        const vertex = new THREE.Vector3();

        // Recreate same noise instance the Generator used
        let rSeed = seed;
        const rng = () => {
            const x = Math.sin(rSeed++) * 10000;
            return x - Math.floor(x);
        };
        const noise2D = createNoise2D(() => rng());

        for (let i = 0; i < pos.count; i++) {
            vertex.fromBufferAttribute(pos, i);

            // Main height from the math utility so objects match exactly
            const h = getTerrainHeight(noise2D, vertex.x, vertex.z);

            // Curve down massively at edges to form a "planet" horizon
            // If we are at dist R from center, we drop it down smoothly.
            const dist = Math.sqrt(vertex.x * vertex.x + vertex.z * vertex.z);
            const edgeRadius = 400;
            let drop = 0;
            if (dist > edgeRadius) {
                // Drop quadratically beyond edgeRadius
                const d = dist - edgeRadius;
                drop = (d * d) * 0.05;
            }

            pos.setY(i, h - drop);
        }

        geo.computeVertexNormals();
        return geo;
    }, [seed]);

    return (
        <mesh geometry={geometry} receiveShadow>
            <meshStandardMaterial
                color="#081830" // Dark blueish surface
                roughness={0.9}
                metalness={0.1}
                wireframe={false}
            />
        </mesh>
    );
};

export default Landscape;
