import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';

interface AssetsStore {
    assets: Assets;

    // Asset CRUD operations
    addAsset: (asset: Asset) => void;
    removeAsset: (modelUuid: string) => void;
    updateAsset: (modelUuid: string, updates: Partial<Asset>) => void;
    clearAssets: () => void;
    resetAsset: (modelUuid: string) => void;
    setAssets: (assets: Assets) => void;

    // Asset properties
    setName: (modelUuid: string, newName: string) => void;
    setPosition: (modelUuid: string, position: [number, number, number]) => void;
    setRotation: (modelUuid: string, rotation: [number, number, number]) => void;
    setLock: (modelUuid: string, isLocked: boolean) => void;
    setCollision: (modelUuid: string, isCollidable: boolean) => void;
    setVisibility: (modelUuid: string, isVisible: boolean) => void;
    setOpacity: (modelUuid: string, opacity: number) => void;

    // Animation controls
    setAnimations: (modelUuid: string, animations: string[]) => void;
    setCurrentAnimation: (modelUuid: string, current: string, isPlaying: boolean, loopAnimation: boolean, isCompleted: boolean) => void;
    setAnimationComplete: (modelUuid: string, isCompleted: boolean) => void;
    resetAnimation: (modelUuid: string) => void;
    addAnimation: (modelUuid: string, animation: string) => void;
    removeAnimation: (modelUuid: string, animation: string) => void;

    // Event data operations
    addEventData: (modelUuid: string, eventData: Asset['eventData']) => void;
    updateEventData: (modelUuid: string, updates: Partial<Asset['eventData']>) => void;
    removeEventData: (modelUuid: string) => void;

    // Helper functions
    getAssetById: (modelUuid: string) => Asset | undefined;
    getAssetByPointUuid: (pointUuid: string) => Asset | undefined;
    hasAsset: (modelUuid: string) => boolean;
}

export const createAssetStore = () => {
    return create<AssetsStore>()(
        immer((set, get) => ({
            assets: [],

            // Asset CRUD operations
            addAsset: (asset) => {
                set((state) => {
                    if (!state.assets.some(a => a.modelUuid === asset.modelUuid)) {
                        state.assets.push(asset);
                    }
                });
            },

            removeAsset: (modelUuid) => {
                set((state) => {
                    state.assets = state.assets.filter(a => a.modelUuid !== modelUuid);
                });
            },

            updateAsset: (modelUuid, updates) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        Object.assign(asset, updates);
                    }
                });
            },

            clearAssets: () => {
                set((state) => {
                    state.assets = [];
                });
            },

            resetAsset: (modelUuid) => {
                const asset = get().assets.find(a => a.modelUuid === modelUuid);
                if (asset) {
                    const clonedAsset = JSON.parse(JSON.stringify(asset));
                    setTimeout(() => {
                        get().removeAsset(asset.modelUuid);
                        setTimeout(() => {
                            get().addAsset(clonedAsset);
                        }, 0);
                    }, 0);
                }
            },

            setAssets: (assets) => {
                set((state) => {
                    state.assets = assets;
                });
            },

            // Asset properties
            setName: (modelUuid, newName) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.modelName = newName;
                    }
                });
            },

            setPosition: (modelUuid, position) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.position = position;
                    }
                });
            },

            setRotation: (modelUuid, rotation) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.rotation = rotation;
                    }
                });
            },

            setLock: (modelUuid, isLocked) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.isLocked = isLocked;
                    }
                });
            },

            setCollision: (modelUuid, isCollidable) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.isCollidable = isCollidable;
                    }
                });
            },

            setVisibility: (modelUuid, isVisible) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.isVisible = isVisible;
                    }
                });
            },

            setOpacity: (modelUuid, opacity) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.opacity = opacity;
                    }
                });
            },

            // Animation controls
            setAnimations: (modelUuid, animations) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.animations = animations;
                        if (!asset.animationState) {
                            asset.animationState = { current: '', isPlaying: false, loopAnimation: true, isCompleted: true };
                        }
                    }
                });
            },

            setCurrentAnimation: (modelUuid, current, isPlaying, loopAnimation, isCompleted) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset?.animationState) {
                        asset.animationState.current = current;
                        asset.animationState.isPlaying = isPlaying;
                        asset.animationState.loopAnimation = loopAnimation;
                        asset.animationState.isCompleted = isCompleted;
                    }
                });
            },

            setAnimationComplete: (modelUuid, isCompleted) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset?.animationState) {
                        asset.animationState.isCompleted = isCompleted;
                    }
                });
            },

            resetAnimation: (modelUuid) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset?.animationState) {
                        asset.animationState.current = '';
                        asset.animationState.isPlaying = true;
                        asset.animationState.loopAnimation = true;
                        asset.animationState.isCompleted = true;
                    }
                });
            },

            addAnimation: (modelUuid, animation) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        if (!asset.animations) {
                            asset.animations = [animation];
                        } else if (!asset.animations.includes(animation)) {
                            asset.animations.push(animation);
                        }
                    }
                });
            },

            removeAnimation: (modelUuid, animation) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset?.animations) {
                        asset.animations = asset.animations.filter(a => a !== animation);
                        if (asset.animationState?.current === animation) {
                            asset.animationState.isPlaying = false;
                            asset.animationState.current = '';
                        }
                    }
                });
            },

            // Event data operations
            addEventData: (modelUuid, eventData) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        asset.eventData = eventData;
                    }
                });
            },

            updateEventData: (modelUuid, updates) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset?.eventData) {
                        asset.eventData = { ...asset.eventData, ...updates };
                    }
                });
            },

            removeEventData: (modelUuid) => {
                set((state) => {
                    const asset = state.assets.find(a => a.modelUuid === modelUuid);
                    if (asset) {
                        delete asset.eventData;
                    }
                });
            },

            // Helper functions
            getAssetById: (modelUuid) => {
                return get().assets.find(a => a.modelUuid === modelUuid);
            },

            getAssetByPointUuid: (pointUuid) => {
                return get().assets.find(asset =>
                    asset.eventData?.point?.uuid === pointUuid ||
                    asset.eventData?.points?.some(p => p.uuid === pointUuid)
                );
            },

            hasAsset: (modelUuid) => {
                return get().assets.some(a => a.modelUuid === modelUuid);
            }
        }))
    )
}

export type AssetStoreType = ReturnType<typeof createAssetStore>;