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;
    clearEvents: () => 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>
    ) => EventsSchema | undefined;

    // 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 createEventStore = () => {
    return 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);
                });
            },

            clearEvents: () => {
                set((state) => {
                    state.events = [];
                });
            },

            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) => {
                let updatedEvent: EventsSchema | undefined;
                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);
                            updatedEvent = JSON.parse(JSON.stringify(event));
                        }
                    } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
                        Object.assign((event as any).point, updates);
                        updatedEvent = JSON.parse(JSON.stringify(event));
                    }
                });
                return updatedEvent;
            },

            // 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;
            }
        }))
    )
}

export type EventStoreType = ReturnType<typeof createEventStore>;