"use client";

import type { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
import { Canvas } from "@react-three/fiber";
import { useGLTF, useAnimations, Environment, Loader, OrbitControls, Bounds } from "@react-three/drei";
import { Suspense, useEffect, useRef, useState } from "react";
import { RotateCw, Play, Pause, Film, Shrink, Expand } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";

import { ScrollArea } from "@/components/ui/scroll-area";
import { useNavigate } from 'react-router';


// Model component
function Model({ url, onAnimationsLoaded, onNodesLoaded }: {
  url: string;
  onAnimationsLoaded: (animations: string[], actions: Record<string, any>) => void;
  onNodesLoaded: (nodes: string[], nodePositions: Record<string, [number, number, number]>) => void;
}) {
  const { scene, animations } = useGLTF(url);
  const { actions } = useAnimations(animations, scene);

  useEffect(() => {
    if (actions) {
      onAnimationsLoaded(animations.map(anim => anim.name), actions);
    }

    if (scene.children) {
      const nodeList = scene.children.map(node => node.name);
      const nodePositions = scene.children.reduce((acc, node) => {
        acc[node.name] = [node.position.x, node.position.y, node.position.z];
        return acc;
      }, {} as Record<string, [number, number, number]>);

      onNodesLoaded(nodeList, nodePositions);
    }
  }, [actions, animations, onAnimationsLoaded, onNodesLoaded]);

  return (
    <Bounds fit margin={.9}>
      {/* find the object in the perfect angle */}

      <primitive object={scene} />
    </Bounds>
  );
}

export default function Previewer({ modelUrl }: { modelUrl: string }) {
  const controlsRef = useRef<OrbitControlsImpl>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [animations, setAnimations] = useState<string[]>([]);
  const [actions, setActions] = useState<Record<string, any>>({});
  const [currentAnimation, setCurrentAnimation] = useState<string | null>(null);

  const [_, setNodes] = useState<string[]>([]);
  const [nodePositions, setNodePositions] = useState<Record<string, [number, number, number]>>({});
  const [isFullscreen, setIsFullscreen] = useState(false);

  const navigate = useNavigate();

  nodePositions;

  const playAnimation = (name: string) => {
    if (actions[name]) {
      Object.values(actions).forEach(action => action.stop()); // Stop other animations
      actions[name].play();
      setCurrentAnimation(name);
    }
  };

  const pauseAnimation = () => {
    if (currentAnimation && actions[currentAnimation]) {
      actions[currentAnimation].stop();
      setCurrentAnimation(null);
    }
  };

  // Handle Fullscreen Mode
  const toggleFullscreen = () => {
    if (!document.fullscreenElement) {
      containerRef.current?.requestFullscreen().then(() => {
        setIsFullscreen(true);
      }).catch(err => {
        console.error("Error entering fullscreen:", err);
      });
    } else {
      document.exitFullscreen().then(() => {
        setIsFullscreen(false);
      }).catch(err => {
        console.error("Error exiting fullscreen:", err);
      });
    }
  };

  return (
    <div ref={containerRef} className="relative w-full grow bg-white/10 shadow-xl shadow-gray-300/25 rounded-lg p-6 backdrop-blur-lg h-100">
      <div className="z-10 absolute top-4 w-100 flex wrap gap-5">
        <Popover>
          <PopoverTrigger className="flex items-center gap-2 bg-gradient-to-r from-blue-600 to-blue-800 text-white px-4 py-2 rounded-lg shadow-lg transition-all duration-300 hover:from-blue-500 hover:to-blue-700">
            <Film className="w-5 h-5" />
            <span>Animaciones</span>
          </PopoverTrigger>

          <PopoverContent className="p-4 bg-blue-900 text-white w-64">
            <ScrollArea className="max-h-60">
              <div className="flex flex-col gap-2">
                {animations.length > 0 ? (
                  animations.map((anim) => (
                    <Button
                      key={anim}
                      className="w-full flex justify-between italic"
                      onClick={() => {
                        if (currentAnimation === anim) {
                          pauseAnimation(); // Pause if it's already playing
                        } else {
                          playAnimation(anim); // Play if it's not currently playing
                        }
                      }}
                    >
                      {anim}
                      {currentAnimation === anim ? <Pause className="w-4 h-4" /> : <Play className="w-4 h-4" />}
                    </Button>
                  ))
                ) : (
                  <p className="text-gray-500 text-center">Este modelo no tiene animaciones.</p>
                )}
              </div>
            </ScrollArea>
          </PopoverContent>
        </Popover>
      </div>
      <div className="absolute bottom-4 right-4 z-10 flex gap-4">
        <Button
          className="bg-gradient-to-r from-red-600 to-red-800 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-red-500 hover:to-red-700 active:scale-95 flex items-center gap-2 justify-center"
          onClick={() => navigate("/")}
        >
          <RotateCw className="w-5 h-5" />
          Regresar al menú
        </Button>
        <Button
          className="bg-gradient-to-r from-gray-700 to-gray-900 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-gray-600 hover:to-gray-800 active:scale-95 flex items-center gap-2 justify-center"
          onClick={toggleFullscreen}        >
          {isFullscreen ? <Shrink className="w-5 h-5" /> : <Expand className="w-5 h-5" />}
          {isFullscreen ? "Salir" : "Pantalla Completa"}
        </Button>
      </div>
      <div className="w-full h-full">
        <Suspense fallback={<Loader />}>
          <Canvas className="w-full h-full">
            <Environment preset="city" />
            <OrbitControls ref={controlsRef} minPolarAngle={Math.PI / 4} maxPolarAngle={Math.PI / 1.5} />
            <Model
              url={modelUrl}

              onAnimationsLoaded={(animNames, actionMap) => {
                setAnimations(animNames);
                setActions(actionMap);
              }}
              onNodesLoaded={(nodeList, nodePos) => {
                setNodes(nodeList);
                setNodePositions(nodePos);
              }}
            />
          </Canvas>
        </Suspense>
      </div>

    </div>
  );
}
