"use client";

import { ContactShadows, Float, RoundedBox } from "@react-three/drei";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { Suspense, useRef } from "react";
import * as THREE from "three";

function Window({
  position,
  size = [0.42, 0.55, 0.08],
}: {
  position: [number, number, number];
  size?: [number, number, number];
}) {
  return (
    <mesh position={position}>
      <boxGeometry args={size} />
      <meshStandardMaterial
        color="#a9e7ff"
        emissive="#168ddb"
        emissiveIntensity={0.45}
        roughness={0.12}
        metalness={0.2}
      />
    </mesh>
  );
}

function Villa() {
  return (
    <group position={[-2.7, 0.15, 0.5]} rotation={[0, 0.22, 0]}>
      <RoundedBox args={[3.2, 1.85, 2.5]} radius={0.16} smoothness={4}>
        <meshStandardMaterial color="#f7fbff" roughness={0.52} />
      </RoundedBox>

      <mesh position={[0, 1.3, 0]} rotation={[0, 0, Math.PI / 4]}>
        <boxGeometry args={[2.32, 2.32, 2.52]} />
        <meshStandardMaterial color="#0a2e77" roughness={0.45} />
      </mesh>

      <RoundedBox
        position={[0, 0.85, 0.12]}
        args={[2.9, 1.32, 2.56]}
        radius={0.12}
        smoothness={4}
      >
        <meshStandardMaterial color="#ffffff" roughness={0.5} />
      </RoundedBox>

      <RoundedBox
        position={[0, 0.47, 1.33]}
        args={[0.66, 1.35, 0.15]}
        radius={0.06}
        smoothness={3}
      >
        <meshStandardMaterial color="#0a2e77" />
      </RoundedBox>

      <Window position={[-0.87, 0.83, 1.35]} />
      <Window position={[0.87, 0.83, 1.35]} />

      <mesh position={[0, 0.09, 1.75]}>
        <boxGeometry args={[1.15, 0.12, 0.75]} />
        <meshStandardMaterial color="#cfd8e5" />
      </mesh>
    </group>
  );
}

function OfficeTower() {
  const windows = [];

  for (let row = 0; row < 6; row += 1) {
    for (let column = 0; column < 3; column += 1) {
      windows.push(
        <Window
          key={`${row}-${column}`}
          position={[
            column * 0.68 - 0.68,
            row * 0.68 - 1.55,
            0.78,
          ]}
          size={[0.42, 0.4, 0.08]}
        />,
      );
    }
  }

  return (
    <group position={[2.25, 2.05, -1]} rotation={[0, -0.18, 0]}>
      <RoundedBox args={[2.6, 5.35, 1.6]} radius={0.18} smoothness={4}>
        <meshStandardMaterial
          color="#0a347d"
          roughness={0.28}
          metalness={0.18}
        />
      </RoundedBox>

      <RoundedBox
        position={[0.48, 0.15, 0.84]}
        args={[1.08, 4.7, 0.08]}
        radius={0.04}
        smoothness={2}
      >
        <meshStandardMaterial
          color="#1196dc"
          emissive="#087fc4"
          emissiveIntensity={0.28}
        />
      </RoundedBox>

      {windows}
    </group>
  );
}

function CommercialBuilding() {
  return (
    <group position={[3.1, 0.55, 2.2]} rotation={[0, -0.22, 0]}>
      <RoundedBox args={[3.4, 2.45, 2.1]} radius={0.2} smoothness={4}>
        <meshStandardMaterial color="#e9f2fa" roughness={0.45} />
      </RoundedBox>

      <RoundedBox
        position={[0, 0.2, 1.1]}
        args={[2.75, 1.3, 0.1]}
        radius={0.05}
        smoothness={2}
      >
        <meshStandardMaterial
          color="#5fcaef"
          emissive="#178fc8"
          emissiveIntensity={0.35}
          metalness={0.25}
          roughness={0.15}
        />
      </RoundedBox>

      <mesh position={[0, -0.83, 1.2]}>
        <boxGeometry args={[2.35, 0.16, 0.5]} />
        <meshStandardMaterial color="#1c4a83" />
      </mesh>
    </group>
  );
}

function Tree({
  position,
  scale = 1,
}: {
  position: [number, number, number];
  scale?: number;
}) {
  return (
    <group position={position} scale={scale}>
      <mesh position={[0, 0.45, 0]}>
        <cylinderGeometry args={[0.09, 0.14, 0.9, 10]} />
        <meshStandardMaterial color="#72543e" />
      </mesh>

      <mesh position={[0, 1.22, 0]}>
        <icosahedronGeometry args={[0.72, 1]} />
        <meshStandardMaterial color="#50ae79" roughness={0.7} />
      </mesh>
    </group>
  );
}

function FuturePlot({
  position,
}: {
  position: [number, number, number];
}) {
  return (
    <Float speed={1.5} rotationIntensity={0.08} floatIntensity={0.18}>
      <group position={position}>
        <RoundedBox args={[1.75, 0.12, 1.75]} radius={0.1} smoothness={3}>
          <meshStandardMaterial
            color="#58c8f4"
            transparent
            opacity={0.34}
            emissive="#1099df"
            emissiveIntensity={0.6}
          />
        </RoundedBox>

        <mesh position={[0, 0.65, 0]}>
          <cylinderGeometry args={[0.035, 0.035, 1.2, 8]} />
          <meshStandardMaterial color="#0c3477" />
        </mesh>

        <mesh position={[0, 1.15, 0]}>
          <octahedronGeometry args={[0.18]} />
          <meshStandardMaterial
            color="#8be5ff"
            emissive="#1da8ed"
            emissiveIntensity={1.4}
          />
        </mesh>
      </group>
    </Float>
  );
}

function CameraRig() {
  const { camera, pointer } = useThree();

  useFrame(() => {
    camera.position.x = THREE.MathUtils.lerp(
      camera.position.x,
      pointer.x * 0.6,
      0.025,
    );

    camera.position.y = THREE.MathUtils.lerp(
      camera.position.y,
      6.2 + pointer.y * 0.3,
      0.025,
    );

    camera.lookAt(0, 0.65, 0);
  });

  return null;
}

function City() {
  const cityRef = useRef<THREE.Group>(null);

  useFrame((state) => {
    if (!cityRef.current) return;

    cityRef.current.rotation.y =
      Math.sin(state.clock.elapsedTime * 0.22) * 0.025;
    cityRef.current.position.y =
      Math.sin(state.clock.elapsedTime * 0.6) * 0.045;
  });

  return (
    <group ref={cityRef}>
      <mesh position={[0, -0.02, 0]}>
        <cylinderGeometry args={[7.5, 7.7, 0.35, 64]} />
        <meshStandardMaterial color="#dceaf2" roughness={0.85} />
      </mesh>

      <mesh position={[0, 0.17, 0]} rotation={[-Math.PI / 2, 0, 0]}>
        <ringGeometry args={[3.7, 5.05, 64]} />
        <meshStandardMaterial color="#9aa9b4" roughness={0.9} />
      </mesh>

      <mesh position={[0, 0.19, 0]} rotation={[-Math.PI / 2, 0, 0]}>
        <ringGeometry args={[4.33, 4.42, 64]} />
        <meshStandardMaterial color="#eef5f9" />
      </mesh>

      <Villa />
      <OfficeTower />
      <CommercialBuilding />

      <Tree position={[-4.8, 0.15, -1.6]} />
      <Tree position={[-4.5, 0.15, 2.5]} scale={0.85} />
      <Tree position={[0.5, 0.15, 3.9]} scale={0.9} />
      <Tree position={[4.85, 0.15, -2.6]} />
      <Tree position={[0.35, 0.15, -4.6]} scale={0.78} />

      <FuturePlot position={[-1.3, 0.26, -3.6]} />
      <FuturePlot position={[4.7, 0.26, 0.15]} />
    </group>
  );
}

export default function CityScene() {
  return (
    <div className="city-canvas" aria-hidden="true">
      <Canvas
        shadows
        dpr={[1, 1.75]}
        camera={{ position: [0, 6.2, 12.5], fov: 42 }}
        gl={{
          antialias: true,
          alpha: true,
          powerPreference: "high-performance",
        }}
      >
        <Suspense fallback={null}>
          <ambientLight intensity={1.8} />
          <hemisphereLight args={["#dff6ff", "#1a2f4f", 2.2]} />

          <directionalLight
            castShadow
            position={[6, 10, 7]}
            intensity={3}
            color="#ffffff"
            shadow-mapSize-width={1024}
            shadow-mapSize-height={1024}
          />

          <pointLight
            position={[-6, 4, 4]}
            color="#32b4f4"
            intensity={25}
            distance={16}
          />

          <City />
          <CameraRig />

          <ContactShadows
            position={[0, -0.19, 0]}
            opacity={0.35}
            scale={18}
            blur={2.8}
            far={10}
          />
        </Suspense>
      </Canvas>
    </div>
  );
}
