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

type MaterialsStore = {
    materials: MaterialsSchema;

    addMaterial: (material: MaterialSchema) => MaterialSchema | undefined;
    removeMaterial: (materialId: string) => MaterialSchema | undefined;
    updateMaterial: (materialId: string, updates: Partial<MaterialSchema>) => MaterialSchema | undefined;

    setCurrentLocation: (
        materialId: string,
        location: {
            modelUuid: string;
            pointUuid: string;
            actionUuid: string;
        }
    ) => MaterialSchema | undefined;

    setNextLocation: (
        materialId: string,
        location?: {
            modelUuid: string;
            pointUuid: string;
            actionUuid: string;
        } | null
    ) => MaterialSchema | undefined;

    setStartTime: (materialId: string, startTime: string) => MaterialSchema | undefined;
    setEndTime: (materialId: string, endTime: string) => MaterialSchema | undefined;
    setCost: (materialId: string, cost: number) => MaterialSchema | undefined;
    setWeight: (materialId: string, weight: number) => MaterialSchema | undefined;
    setIsActive: (materialId: string, isActive: boolean) => MaterialSchema | undefined;
    setIsVisible: (materialId: string, isVisible: boolean) => MaterialSchema | undefined;
    setIsRendered: (materialId: string, isRendered: boolean) => MaterialSchema | undefined;

    getMaterialById: (materialId: string) => MaterialSchema | undefined;
    getMaterialsByPoint: (pointUuid: string) => MaterialSchema[];
    getMaterialsByModel: (modelUuid: string) => MaterialSchema[];
};

export const useMaterialStore = create<MaterialsStore>()(
    immer((set, get) => ({
        materials: [],

        addMaterial: (material) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                state.materials.push(material);
            });
            return updatedMaterial;
        },

        removeMaterial: (materialId) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    state.materials.filter(m => m.materialId !== material.materialId);
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                }
            });
            return updatedMaterial;
        },

        updateMaterial: (materialId, updates) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    Object.assign(material, updates);
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                }
            });
            return updatedMaterial;
        },

        setCurrentLocation: (materialId, location) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.current = location;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                }
            });
            return updatedMaterial;
        },

        setNextLocation: (materialId, location) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.next = location || undefined;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                }
            });
            return updatedMaterial;
        },

        setStartTime: (materialId, startTime) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.startTime = startTime
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        setEndTime: (materialId, endTime) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.endTime = endTime;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        setCost: (materialId, cost) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.cost = cost;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        setWeight: (materialId, weight) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.weight = weight;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        setIsActive: (materialId, isActive) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.isActive = isActive;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        setIsVisible: (materialId, isVisible) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.isVisible = isVisible;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        setIsRendered: (materialId, isRendered) => {
            let updatedMaterial: MaterialSchema | undefined;
            set((state) => {
                const material = state.materials.find(m => m.materialId === materialId);
                if (material) {
                    material.isRendered = isRendered;
                    updatedMaterial = JSON.parse(JSON.stringify(material));
                };
            });
            return updatedMaterial;
        },

        getMaterialById: (materialId) => {
            return get().materials.find(m => m.materialId === materialId);
        },

        getMaterialsByPoint: (pointUuid) => {
            return get().materials.filter(m =>
                m.current?.pointUuid === pointUuid ||
                m.next?.pointUuid === pointUuid
            );
        },

        getMaterialsByModel: (modelUuid) => {
            return get().materials.filter(m =>
                m.current?.modelUuid === modelUuid ||
                m.next?.modelUuid === modelUuid
            );
        },
    }))
);