import { Canvas } from "@react-three/fiber";
import { OrbitControls, Stage, useGLTF } from "@react-three/drei";
import { useEffect, Suspense } from "react";
import { Box, CircularProgress, Typography } from "@mui/material";

const clearGLTFCache = (url?: string) => {
  try {
    if (url) {
      if (url.startsWith("blob:")) {
        useGLTF.clear(url);
      } else {
        useGLTF.clear(url);
      }
    }
  } catch (error) {
    console.warn("⚠️ clearGLTFCache: Ошибка при очистке кеша", error);
  }
};

const isValid3DFile = (url: string): boolean => {
  try {
    const urlObj = new URL(url);
    const pathname = urlObj.pathname.toLowerCase();
    const searchParams = urlObj.searchParams;

    const validExtensions = [".glb", ".gltf"];
    const hasValidExtension = validExtensions.some((ext) =>
      pathname.endsWith(ext)
    );

    const fileType = searchParams.get("type") || searchParams.get("format");
    const hasValidType =
      fileType && ["glb", "gltf"].includes(fileType.toLowerCase());

    const isBlobUrl = url.startsWith("blob:");

    const hasToken = searchParams.has("token");
    const isServerUrl = hasToken && !hasValidExtension;

    const isValid =
      hasValidExtension || hasValidType || isBlobUrl || isServerUrl;

    return isValid;
  } catch (error) {
    console.warn("⚠️ isValid3DFile: Ошибка при проверке URL", error);

    return true;
  }
};

type ModelViewerProps = {
  width?: string;
  fileUrl: string;
  height?: string;
};

const Model = ({ fileUrl }: { fileUrl: string }) => {
  useEffect(() => {
    clearGLTFCache(fileUrl);
  }, [fileUrl]);

  if (fileUrl.startsWith("blob:") && !isValid3DFile(fileUrl)) {
    console.warn("⚠️ Model: Попытка загрузить невалидный 3D файл", { fileUrl });
    throw new Error(`Файл не является корректной 3D моделью: ${fileUrl}`);
  }

  const { scene } = useGLTF(fileUrl);
  return <primitive object={scene} />;
};

const LoadingFallback = () => {
  return (
    <Box
      sx={{
        position: "absolute",
        top: "50%",
        left: "50%",
        transform: "translate(-50%, -50%)",
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        gap: 2,
        zIndex: 1000,
        backgroundColor: "background.paper",
        p: 3,
        borderRadius: 2,
      }}
    >
      <CircularProgress size={48} />
      <Typography
        variant="body2"
        color="text.secondary"
        style={{ whiteSpace: "nowrap" }}
      >
        Загрузка 3D модели...
      </Typography>
    </Box>
  );
};

export const ThreeView = ({
  fileUrl,
  height = "100%",
  width = "100%",
}: ModelViewerProps) => {
  useEffect(() => {
    if (fileUrl.startsWith("blob:") && !isValid3DFile(fileUrl)) {
      console.warn("⚠️ ThreeView: Невалидный 3D файл", { fileUrl });
    }
  }, [fileUrl]);

  useEffect(() => {
    clearGLTFCache(fileUrl);

    return () => {
      clearGLTFCache(fileUrl);
    };
  }, [fileUrl]);

  return (
    <Box sx={{ position: "relative", width, height }}>
      <Suspense fallback={<LoadingFallback />}>
        <Canvas
          style={{ height: height, width: width }}
          camera={{
            position: [1, 1, 1],
            fov: 30,
          }}
        >
          <ambientLight />
          <directionalLight />
          <Stage environment={null} intensity={0.6} adjustCamera={false}>
            <Model fileUrl={fileUrl} />
          </Stage>
          <OrbitControls />
        </Canvas>
      </Suspense>
    </Box>
  );
};
