"use client";

import type { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
import { Canvas } from "@react-three/fiber";
import { useGLTF, useAnimations, Environment, Loader, OrbitControls, Html } from "@react-three/drei";
import { Suspense, useEffect, useRef, useState } from "react";
import { RotateCw, Play, Pause, Film, ListTree, 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";


// Model component
function Model({ url, position, rotation, scale, onAnimationsLoaded, onNodesLoaded }: {
  url: string;
  position: [number, number, number];
  rotation: number;
  scale: number;
  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 (
    <>
      <primitive object={scene} scale={scale} position={position} rotation={[0, rotation, 0]} />
      {scene.children.map((node, index) => (
        <Html key={index} position={[node.position.x, node.position.y + 0.5, node.position.z]}>
          <div className="bg-blue-500 text-white px-2 py-1 rounded-md text-xs shadow-md">
            {node.name}
          </div>
        </Html>
      ))}
    </>
  );
}
// Preload the model
// useGLTF.preload("/3d/motor_de_combustion/scene.gltf");

const InitialParams = {
  position: [0, -2, 0] as [number, number, number],
  rotation: -Math.PI / 2,
  scale: 0.01,
};

// Main 3D Viewer
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 [nodes, setNodes] = useState<string[]>([]);
  const [nodePositions, setNodePositions] = useState<Record<string, [number, number, number]>>({});
  const [isFullscreen, setIsFullscreen] = useState(false);

  nodePositions;


  const resetView = () => {
    if (controlsRef.current) {
      controlsRef.current.reset();
    }
  };

  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>

        <Popover>
          <PopoverTrigger className="flex items-center gap-2 bg-gradient-to-r from-blue-100 to-blue-50 text-blue-500 px-4 py-2 rounded-lg shadow-lg transition-all duration-300 hover:from-blue-100 hover:to-blue-200">
            <ListTree />
            Partes del modelo
          </PopoverTrigger>
          <PopoverContent className="p-4 bg-blue-50 text-white w-64">
            <ScrollArea className="max-h-60">
              <div className="flex flex-col gap-2">
                {nodes.length > 0 ? (
                  nodes.map((node, index) => (
                    <div key={index} className="bg-blue-900/10 p-2 rounded-lg text-center text-blue-700">
                      {node}
                    </div>
                  ))
                ) : (
                  <p className="text-blue-500 text-center">Este modelo no tiene partes.</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={resetView}
        >
          <RotateCw className="w-5 h-5" />
          Centrar cámara
        </Button>

        {/* Botón de pantalla completa */}
        <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 camera={{ position: [0, 0, 12], fov: 20 }}>
            <Environment preset="city" />
            <OrbitControls ref={controlsRef} />
            <Model
              url={modelUrl}
              position={InitialParams.position}
              rotation={InitialParams.rotation}
              scale={InitialParams.scale}
              onAnimationsLoaded={(animNames, actionMap) => {
                setAnimations(animNames);
                setActions(actionMap);
              }}
              onNodesLoaded={(nodeList, nodePos) => {
                setNodes(nodeList);
                setNodePositions(nodePos);
              }}
            />
          </Canvas>
        </Suspense>
      </div>

    </div>
  );
}
