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

type EventsStore = {
    events: EventsSchema[];

    // Event-level actions
    addEvent: (event: EventsSchema) => void;
    removeEvent: (modelUuid: string) => void;
    updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;

    // Point-level actions
    addPoint: (modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
    removePoint: (modelUuid: string, pointUuid: string) => void;
    updatePoint: (
        modelUuid: string,
        pointUuid: string,
        updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
    ) => void;

    // Action-level actions
    addAction: (
        modelUuid: string,
        pointUuid: string,
        action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
    ) => void;
    removeAction: (actionUuid: string) => void;
    updateAction: (
        actionUuid: string,
        updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
    ) => void;

    // Trigger-level actions
    addTrigger: (actionUuid: string, trigger: TriggerSchema) => void;
    removeTrigger: (triggerUuid: string) => void;
    updateTrigger: (triggerUuid: string, updates: Partial<TriggerSchema>) => void;

    // Helper functions
    getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined;
    getPointByUuid: (modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
    getActionByUuid: (actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
    getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
};

export const useEventsStore = create<EventsStore>()(
    immer((set, get) => ({
        events: [],

        // Event-level actions
        addEvent: (event) => {
            set((state) => {
                if (!state.events.some(e => 'modelUuid' in e && e.modelUuid === event.modelUuid)) {
                    state.events.push(event);
                }
            });
        },

        removeEvent: (modelUuid) => {
            set((state) => {
                state.events = state.events.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
            });
        },

        updateEvent: (modelUuid, updates) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
                if (event) {
                    Object.assign(event, updates);
                    updatedEvent = JSON.parse(JSON.stringify(event));
                }
            });
            return updatedEvent;
        },

        // Point-level actions
        addPoint: (modelUuid, point) => {
            set((state) => {
                const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
                if (event && 'points' in event) {
                    const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid);
                    if (!existingPoint) {
                        (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
                    }
                } else if (event && 'point' in event) {
                    if (!(event as any).point || (event as any).point.uuid !== point.uuid) {
                        (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
                    }
                }
            });
        },

        removePoint: (modelUuid, pointUuid) => {
            set((state) => {
                const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
                if (event && 'points' in event) {
                    (event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
                }
                // For single-point events, you might want to handle differently
            });
        },

        updatePoint: (modelUuid, pointUuid, updates) => {
            set((state) => {
                const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
                if (event && 'points' in event) {
                    const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
                    if (point) {
                        Object.assign(point, updates);
                    }
                } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
                    Object.assign((event as any).point, updates);
                }
            });
        },

        // Action-level actions
        addAction: (modelUuid, pointUuid, action) => {
            set((state) => {
                const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
                if (event && 'points' in event) {
                    const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
                    if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) {
                        point.action = action as any;
                    }
                } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
                    const point = (event as any).point;
                    if ('action' in point && (!point.action || point.action.actionUuid !== action.actionUuid)) {
                        point.action = action;
                    } else if ('actions' in point && !point.actions.some((a: any) => a.actionUuid === action.actionUuid)) {
                        point.actions.push(action);
                    }
                }
            });
        },

        removeAction: (actionUuid) => {
            set((state) => {
                for (const event of state.events) {
                    if ('points' in event) {
                        for (const point of (event as ConveyorEventSchema).points) {
                            if (point.action && point.action.actionUuid === actionUuid) {
                                // Handle removal for single action points
                            }
                        }
                    } else if ('point' in event) {
                        const point = (event as any).point;
                        if (event.type === "roboticArm") {
                            if ('actions' in point) {
                                point.actions = point.actions.filter((a: any) => a.actionUuid !== actionUuid);
                            }
                        } else if ('action' in point && point.action?.actionUuid === actionUuid) {
                            // Handle single action
                        }
                    }
                }
            });
        },

        updateAction: (actionUuid, updates) => {
            set((state) => {
                for (const event of state.events) {
                    if ('points' in event) {
                        for (const point of (event as ConveyorEventSchema).points) {
                            if (point.action && point.action.actionUuid === actionUuid) {
                                Object.assign(point.action, updates);
                                return;
                            }
                        }
                    } else if ('point' in event) {
                        const point = (event as any).point;
                        if ('action' in point && point.action.actionUuid === actionUuid) {
                            Object.assign(point.action, updates);
                            return;
                        } else if ('actions' in point) {
                            const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                            if (action) {
                                Object.assign(action, updates);
                                return;
                            }
                        }
                    }
                }
            });
        },

        // Trigger-level actions
        addTrigger: (actionUuid, trigger) => {
            set((state) => {
                for (const event of state.events) {
                    if ('points' in event) {
                        for (const point of (event as ConveyorEventSchema).points) {
                            if (point.action && point.action.actionUuid === actionUuid) {
                                if (!point.action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) {
                                    point.action.triggers.push(trigger);
                                }
                                return;
                            }
                        }
                    } else if ('point' in event) {
                        const point: MachinePointSchema | VehiclePointSchema = (event as any).point;
                        if ('action' in point && point.action.actionUuid === actionUuid) {
                            if (!point.action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) {
                                point.action.triggers.push(trigger);
                            }
                            return;
                        } else if ('actions' in point) {
                            const action = (point as RoboticArmPointSchema).actions.find((a) => a.actionUuid === actionUuid);
                            if (action && !action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) {
                                action.triggers.push(trigger);
                                return;
                            }
                        }
                    }
                }
            });
        },

        removeTrigger: (triggerUuid) => {
            set((state) => {
                for (const event of state.events) {
                    if ('points' in event) {
                        for (const point of (event as ConveyorEventSchema).points) {
                            if (point.action && 'triggers' in point.action) {
                                point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
                            }
                        }
                    } else if ('point' in event) {
                        const point = (event as any).point;
                        if ('action' in point && 'triggers' in point.action) {
                            point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
                        } else if ('actions' in point) {
                            for (const action of point.actions) {
                                if ('triggers' in action) {
                                    action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
                                }
                            }
                        }
                    }
                }
            });
        },

        updateTrigger: (triggerUuid, updates) => {
            set((state) => {
                for (const event of state.events) {
                    if ('points' in event) {
                        for (const point of (event as ConveyorEventSchema).points) {
                            if (point.action && 'triggers' in point.action) {
                                const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
                                if (trigger) {
                                    Object.assign(trigger, updates);
                                    return;
                                }
                            }
                        }
                    } else if ('point' in event) {
                        const point = (event as any).point;
                        if ('action' in point && 'triggers' in point.action) {
                            const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
                            if (trigger) {
                                Object.assign(trigger, updates);
                                return;
                            }
                        } else if ('actions' in point) {
                            for (const action of point.actions) {
                                if ('triggers' in action) {
                                    const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
                                    if (trigger) {
                                        Object.assign(trigger, updates);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            });
        },

        // Helper functions
        getEventByModelUuid: (modelUuid) => {
            return get().events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
        },

        getPointByUuid: (modelUuid, pointUuid) => {
            const event = get().events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
            if (event && 'points' in event) {
                return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
            } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
                return (event as any).point;
            }
            return undefined;
        },

        getActionByUuid: (actionUuid) => {
            const state = get();
            for (const event of state.events) {
                if ('points' in event) {
                    for (const point of (event as ConveyorEventSchema).points) {
                        if (point.action && point.action.actionUuid === actionUuid) {
                            return point.action;
                        }
                    }
                } else if ('point' in event) {
                    const point = (event as any).point;
                    if ('action' in point && point.action.actionUuid === actionUuid) {
                        return point.action;
                    } else if ('actions' in point) {
                        const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                        if (action) return action;
                    }
                }
            }
            return undefined;
        },

        getTriggerByUuid: (triggerUuid) => {
            const state = get();
            for (const event of state.events) {
                if ('points' in event) {
                    for (const point of (event as ConveyorEventSchema).points) {
                        if (point.action && 'triggers' in point.action) {
                            const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
                            if (trigger) return trigger;
                        }
                    }
                } else if ('point' in event) {
                    const point = (event as any).point;
                    if ('action' in point && 'triggers' in point.action) {
                        const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
                        if (trigger) return trigger;
                    } else if ('actions' in point) {
                        for (const action of point.actions) {
                            if ('triggers' in action) {
                                const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
                                if (trigger) return trigger;
                            }
                        }
                    }
                }
            }
            return undefined;
        }
    }))
);