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

interface VehiclesStore {
    vehicles: VehicleStatus[];

    addVehicle: (productUuid: string, event: VehicleEventSchema) => void;
    removeVehicle: (modelUuid: string) => void;
    updateVehicle: (
        modelUuid: string,
        updates: Partial<Omit<VehicleStatus, "modelUuid" | "productUuid">>
    ) => void;
    addPathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], point: VehicleAction["paths"]["initPickup"][number]) => VehicleAction["paths"];
    updatePathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], pointId: string, updates: Partial<VehicleAction["paths"]["initPickup"][number]>) => VehicleAction["paths"];
    deletePathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], pointId: string) => VehicleAction["paths"];
    clearVehicles: () => void;

    setVehicleActive: (modelUuid: string, isActive: boolean) => void;
    setVehiclePicking: (modelUuid: string, isPicking: boolean) => void;
    updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void;
    incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
    decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
    setVehicleLoad: (modelUuid: string, load: number) => void;
    setVehicleState: (
        modelUuid: string,
        newState: VehicleStatus["state"]
    ) => void;
    addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
    setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void;
    removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
    getLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
    clearCurrentMaterials: (modelUuid: string) => void;
    incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
    incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
    resetTime: (modelUuid: string) => void;

    getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
    getVehiclesByProduct: (productUuid: string) => VehicleStatus[];
    getVehiclesByState: (state: string) => VehicleStatus[];
    getActiveVehicles: () => VehicleStatus[];
}

export const createVehicleStore = () => {
    return create<VehiclesStore>()(
        immer((set, get) => ({
            vehicles: [],

            addVehicle: (productUuid, event) => {
                set((state) => {
                    const exists = state.vehicles.some((v) => v.modelUuid === event.modelUuid);
                    if (!exists) {
                        state.vehicles.push({
                            ...event,
                            productUuid,
                            isActive: false,
                            isPicking: false,
                            idleTime: 0,
                            activeTime: 0,
                            currentLoad: 0,
                            currentMaterials: [],
                            distanceTraveled: 0,
                            state: 'idle'
                        });
                    }
                });
            },

            removeVehicle: (modelUuid) => {
                set((state) => {
                    state.vehicles = state.vehicles.filter(
                        (v) => v.modelUuid !== modelUuid
                    );
                });
            },

            updateVehicle: (modelUuid, updates) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        Object.assign(vehicle, updates);
                    }
                });
            },

            addPathPoint: (modelUuid, pathKey, point) => {
                let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
                set((state) => {
                    const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
                    if (vehicle) {
                        const path = vehicle.point.action.paths[pathKey];
                        path.push(point);
                        updatedPaths = vehicle.point.action.paths;
                    }
                });
                return updatedPaths;
            },

            updatePathPoint: (modelUuid, pathKey, pointId, updates) => {
                let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
                set((state) => {
                    const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
                    if (vehicle) {
                        const path = vehicle.point.action.paths[pathKey];
                        const index = path.findIndex(p => p.pointId === pointId);
                        if (index !== -1) {
                            Object.assign(path[index], updates);
                            updatedPaths = vehicle.point.action.paths;
                        }
                    }
                });
                return updatedPaths;
            },

            deletePathPoint: (modelUuid, pathKey, pointId) => {
                let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
                set((state) => {
                    const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
                    if (vehicle) {
                        const path = vehicle.point.action.paths[pathKey];
                        vehicle.point.action.paths[pathKey] = path.filter(p => p.pointId !== pointId);
                        updatedPaths = vehicle.point.action.paths;
                    }
                });
                return updatedPaths;
            },

            clearVehicles: () => {
                set((state) => {
                    state.vehicles = [];
                });
            },

            setVehicleActive: (modelUuid, isActive) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.isActive = isActive;
                    }
                });
            },

            setVehiclePicking: (modelUuid, isPicking) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.isPicking = isPicking;
                    }
                });
            },

            updateSteeringAngle: (modelUuid, steeringAngle) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.point.action.steeringAngle = steeringAngle;
                    }
                });
            },

            incrementVehicleLoad: (modelUuid, incrementBy) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.currentLoad += incrementBy;
                    }
                });
            },

            decrementVehicleLoad: (modelUuid, decrementBy) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.currentLoad -= decrementBy;
                    }
                });
            },

            setVehicleLoad: (modelUuid, load) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.currentLoad = load;
                    }
                });
            },

            setVehicleState: (modelUuid, newState) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.state = newState;
                    }
                });
            },

            addCurrentMaterial: (modelUuid, materialType, materialId) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.currentMaterials.push({ materialType, materialId });
                    }
                });
            },

            setCurrentMaterials: (modelUuid, materials) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.currentMaterials = materials;
                    }
                });
            },

            removeLastMaterial: (modelUuid) => {
                let removedMaterial: { materialId: string; materialType: string; } | undefined;
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        if (vehicle.currentMaterials.length > 0) {
                            const material = vehicle.currentMaterials.pop();
                            if (material) {
                                removedMaterial = { materialId: material.materialId, materialType: material.materialType };
                            }
                        }
                    }
                });
                return removedMaterial;
            },

            getLastMaterial: (modelUuid) => {
                let removedMaterial: { materialId: string; materialType: string; } | undefined;
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        if (vehicle.currentMaterials.length > 0) {
                            removedMaterial = {
                                materialId: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialId,
                                materialType: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialType
                            };
                        }
                    }
                });
                return removedMaterial;
            },

            clearCurrentMaterials: (modelUuid) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.currentMaterials = [];
                    }
                });
            },

            incrementActiveTime: (modelUuid, incrementBy) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.activeTime += incrementBy;
                    }
                });
            },

            incrementIdleTime: (modelUuid, incrementBy) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.idleTime += incrementBy;
                    }
                });
            },

            resetTime: (modelUuid) => {
                set((state) => {
                    const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
                    if (vehicle) {
                        vehicle.activeTime = 0;
                        vehicle.idleTime = 0;
                    }
                });
            },

            getVehicleById: (modelUuid) => {
                return get().vehicles.find((v) => v.modelUuid === modelUuid);
            },

            getVehiclesByProduct: (productUuid) => {
                return get().vehicles.filter((v) => v.productUuid === productUuid);
            },

            getVehiclesByState: (state) => {
                return get().vehicles.filter((v) => v.state === state);
            },

            getActiveVehicles: () => {
                return get().vehicles.filter((v) => v.isActive);
            },
        }))
    )
}

export type VehicleStoreType = ReturnType<typeof createVehicleStore>;