import { Canvas } from "@react-three/fiber";
import { Component, Suspense, useEffect, useState, type ErrorInfo, type ReactNode } from "react";
import * as THREE from "three";
import { useWorldUi } from "@/lib/world-input";
import { WorldScene } from "./scene";

class WebGLBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {
  state = { failed: false };
  static getDerivedStateFromError() {
    return { failed: true };
  }
  componentDidCatch(error: Error, info: ErrorInfo) {
    console.error("STRATA ridge failed", error, info);
    useWorldUi.setState({ webgl: false });
  }
  render() {
    if (this.state.failed) return null;
    return this.props.children;
  }
}

function Boot() {
  return (
    <div className="absolute inset-0 z-10 flex flex-col items-center justify-center bg-bg text-fg">
      <p className="font-display text-5xl">STRATA</p>
      <p className="mt-3 text-sm tracking-[0.18em] text-muted uppercase">The ridge is assembling</p>
    </div>
  );
}

function RidgeCanvas() {
  return (
    <Canvas
      className="world-canvas h-full w-full"
      camera={{ fov: 60, position: [0, 1.7, 14], near: 0.1, far: 140 }}
      dpr={[1, 1.6]}
      shadows
      gl={{
        antialias: true,
        toneMapping: THREE.ACESFilmicToneMapping,
        toneMappingExposure: 1.05,
        powerPreference: "high-performance",
      }}
      onCreated={({ gl }) => {
        gl.setClearColor("#b9a894", 1);
      }}
    >
      <Suspense fallback={null}>
        <WorldScene />
      </Suspense>
    </Canvas>
  );
}

export function WorldCanvas() {
  const [ready, setReady] = useState(false);
  useEffect(() => setReady(true), []);
  if (!ready) return <Boot />;
  return (
    <WebGLBoundary>
      <div className="absolute inset-0">
        <Suspense fallback={<Boot />}>
          <RidgeCanvas />
        </Suspense>
      </div>
    </WebGLBoundary>
  );
}

export function FallbackLanding() {
  return (
    <div className="flex min-h-dvh flex-col bg-bg px-6 pt-24 text-fg">
      <p className="font-display text-5xl">STRATA</p>
      <p className="mt-4 max-w-md text-muted">
        The ridge needs WebGL. The libraries and store are still open.
      </p>
    </div>
  );
}
