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";

// Утилита для очистки кеша GLTF
const clearGLTFCache = (url?: string) => {
  try {
    if (url) {
      // Если это blob URL, очищаем его из кеша
      if (url.startsWith("blob:")) {
        useGLTF.clear(url);
        console.log("🧹 clearGLTFCache: Очистка blob URL из кеша GLTF", {
          url,
        });
      } else {
        useGLTF.clear(url);
        console.log("🧹 clearGLTFCache: Очистка кеша для URL", { url });
      }
    } else {
      // Очищаем весь кеш GLTF
      useGLTF.clear();
      console.log("🧹 clearGLTFCache: Очистка всего кеша GLTF");
    }
  } 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());

    // Если это blob URL, считаем его валидным (пользователь выбрал файл)
    const isBlobUrl = url.startsWith("blob:");

    // Если это URL с токеном и нет явного расширения, считаем валидным
    // (предполагаем что сервер вернет правильный файл)
    const hasToken = searchParams.has("token");
    const isServerUrl = hasToken && !hasValidExtension;

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

    console.log("🔍 isValid3DFile: Проверка файла", {
      url,
      pathname,
      hasValidExtension,
      fileType,
      hasValidType,
      isBlobUrl,
      isServerUrl,
      isValid,
    });

    return isValid;
  } catch (error) {
    console.warn("⚠️ isValid3DFile: Ошибка при проверке URL", error);
    // В случае ошибки парсинга URL, считаем валидным (пусть useGLTF сам разберется)
    return true;
  }
};

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

const Model = ({ fileUrl }: { fileUrl: string }) => {
  // Очищаем кеш перед загрузкой новой модели
  useEffect(() => {
    // Очищаем кеш для текущего URL
    clearGLTFCache(fileUrl);
  }, [fileUrl]);

  // Проверяем валидность файла перед загрузкой (только для blob URL)
  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) => {
  // Проверяем валидность файла (только для blob URL)
  useEffect(() => {
    if (fileUrl.startsWith("blob:") && !isValid3DFile(fileUrl)) {
      console.warn("⚠️ ThreeView: Невалидный 3D файл", { fileUrl });
    }
  }, [fileUrl]);

  // Очищаем кеш при размонтировании и при смене URL
  useEffect(() => {
    // Очищаем кеш сразу при монтировании компонента
    clearGLTFCache(fileUrl);
    console.log("🧹 ThreeView: Очистка кеша модели при монтировании", {
      fileUrl,
    });

    return () => {
      clearGLTFCache(fileUrl);
      console.log("🧹 ThreeView: Очистка кеша модели при размонтировании", {
        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="city" intensity={0.6} adjustCamera={false}>
            <Model fileUrl={fileUrl} />
          </Stage>
          <OrbitControls />
        </Canvas>
      </Suspense>
    </Box>
  );
};
