import { Outlines } from '@react-three/drei';
import { useEffect, useState } from 'react';
import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import * as THREE from 'three';

function Model({ asset }: { asset: Asset }) {
    const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
    const [gltfScene, setGltfScene] = useState<GLTF | null>(null);

    useEffect(() => {
        const loader = new GLTFLoader();
        const dracoLoader = new DRACOLoader();

        dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
        loader.setDRACOLoader(dracoLoader);
        const loadModel = async () => {
            try {
                const cachedModel = THREE.Cache.get(asset.assetId!);
                if (cachedModel) {
                    setGltfScene(cachedModel);
                    return;
                }

                // Check IndexedDB
                const indexedDBModel = await retrieveGLTF(asset.assetId!);
                if (indexedDBModel) {
                    const blobUrl = URL.createObjectURL(indexedDBModel);
                    loader.load(blobUrl, (gltf) => {
                        URL.revokeObjectURL(blobUrl);
                        THREE.Cache.remove(blobUrl);
                        THREE.Cache.add(asset.assetId!, gltf);
                        setGltfScene(gltf);
                    },
                        undefined,
                        (error) => {
                            echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
                            URL.revokeObjectURL(blobUrl);
                        }
                    );
                    return;
                }

                // Fetch from Backend
                const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${asset.assetId!}`;
                loader.load(modelUrl, async (gltf) => {
                    const modelBlob = await fetch(modelUrl).then((res) => res.blob());
                    await storeGLTF(asset.assetId!, modelBlob);
                    THREE.Cache.add(asset.assetId!, gltf);
                    setGltfScene(gltf);
                },
                    undefined,
                    (error) => {
                        echo.error(`[Backend] Error loading ${asset.modelName}:`);
                    }
                );
            } catch (err) {
                console.error("Failed to load model:", asset.assetId, err);
            }
        };

        loadModel();

    }, [asset.assetId]);

    return (
        <>
            {gltfScene &&
                <group
                    position={asset.position}
                    rotation={asset.rotation}
                    visible={asset.isVisible}
                >
                    <primitive object={gltfScene.scene.clone()} />
                </group>
            }
        </>
    );
}

export default Model;