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

type ProductsStore = {
    products: productsSchema;

    // Product-level actions
    addProduct: (productName: string, productId: string) => void;
    setProducts: (products: productsSchema) => void;
    removeProduct: (productId: string) => void;
    updateProduct: (productId: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;

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

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

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

    // Trigger-level actionss
    addTrigger: (
        productId: string,
        actionUuid: string,
        trigger: TriggerSchema
    ) => EventsSchema | undefined;
    removeTrigger: (productId: string, triggerUuid: string) => EventsSchema | undefined;
    updateTrigger: (
        productId: string,
        triggerUuid: string,
        updates: Partial<TriggerSchema>
    ) => EventsSchema | undefined;

    // Renaming functions
    renameProduct: (productId: string, newName: string) => void;
    renameAction: (productId: string, actionUuid: string, newName: string) => EventsSchema | undefined;
    renameTrigger: (productId: string, triggerUuid: string, newName: string) => EventsSchema | undefined;

    // Helper functions
    getProductById: (productId: string) => { productName: string; productId: string; eventDatas: EventsSchema[] } | undefined;
    getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
    getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
    getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
    getModelUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
    getPointUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
    getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined;
    getIsEventInProduct: (productId: string, modelUuid: string) => boolean;
};

export const useProductStore = create<ProductsStore>()(
    immer((set, get) => ({
        products: [],

        // Product-level actions
        addProduct: (productName, productId) => {
            set((state) => {
                const existingProduct = state.products.find(p => p.productId === productId);
                if (!existingProduct) {
                    const newProduct = {
                        productName,
                        productId: productId,
                        eventDatas: []
                    };
                    state.products.push(newProduct);
                }
            });
        },

        setProducts: (products) => {
            set((state) => {
                state.products = products;
            });
        },

        removeProduct: (productId) => {
            set((state) => {
                state.products = state.products.filter(p => p.productId !== productId);
            });
        },

        updateProduct: (productId, updates) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    Object.assign(product, updates);
                }
            });
        },

        // Event-level actions
        addEvent: (productId, event) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    const existingEvent = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === event.modelUuid);
                    if (!existingEvent) {
                        product.eventDatas.push(event);
                    }
                }
            });
        },

        removeEvent: (productId, modelUuid) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
                }
            });
        },

        deleteEvent: (modelUuid) => {
            set((state) => {
                for (const product of state.products) {
                    product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
                }
            });
        },

        updateEvent: (productId, modelUuid, updates) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    const event = product.eventDatas.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: (productId, modelUuid, point) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    const event = product.eventDatas.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) {
                        const existingPoint = (event as any).point?.uuid === point.uuid;
                        if (!existingPoint) {
                            (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
                        }
                    }
                }
            });
        },

        removePoint: (productId, modelUuid, pointUuid) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    const event = product.eventDatas.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);
                    } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
                        // For events with single point, we can't remove it, only reset to empty
                    }
                }
            });
        },

        updatePoint: (productId, modelUuid, pointUuid, updates) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    const event = product.eventDatas.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: (productId, modelUuid, pointUuid, action) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    const event = product.eventDatas.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;
                            updatedEvent = JSON.parse(JSON.stringify(event));
                        }
                    } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
                        if ('action' in (event as any).point) {
                            if (!(event as any).point.action || (event as any).point.action.actionUuid !== action.actionUuid) {
                                (event as any).point.action = action;
                                updatedEvent = JSON.parse(JSON.stringify(event));
                            }
                        } else if ('actions' in (event as any).point) {
                            const existingAction = (event as any).point.actions.find((a: any) => a.actionUuid === action.actionUuid);
                            if (!existingAction) {
                                (event as any).point.actions.push(action);
                                updatedEvent = JSON.parse(JSON.stringify(event));
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        removeAction: (productId, actionUuid) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        if ('points' in event) {
                            // Handle ConveyorEventSchema
                            for (const point of (event as ConveyorEventSchema).points) {
                            }
                        } else if ('point' in event) {
                            const point = (event as any).point;
                            if (event.type === "roboticArm") {
                                if ('actions' in point) {
                                    const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
                                    if (index !== -1) {
                                        point.actions.splice(index, 1);
                                        updatedEvent = JSON.parse(JSON.stringify(event));
                                        return;
                                    }
                                }
                            } else if ('action' in point && point.action?.actionUuid === actionUuid) {
                                point.action = undefined;
                                updatedEvent = JSON.parse(JSON.stringify(event));
                                return;
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        updateAction: (productId, actionUuid, updates) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        if ('points' in event) {
                            for (const point of (event as ConveyorEventSchema).points) {
                                if (point.action && point.action.actionUuid === actionUuid) {
                                    Object.assign(point.action, updates);
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                    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);
                                updatedEvent = JSON.parse(JSON.stringify(event));
                                return;
                            } else if ('actions' in point) {
                                const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                                if (action) {
                                    Object.assign(action, updates);
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                    return;
                                }
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        // Trigger-level actions
        addTrigger: (productId, actionUuid, trigger) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        if ('points' in event) {
                            for (const point of (event as ConveyorEventSchema).points) {
                                if (point.action && point.action.actionUuid === actionUuid) {
                                    const existingTrigger = point.action.triggers.find(t => t.triggerUuid === trigger.triggerUuid);
                                    if (!existingTrigger) {
                                        point.action.triggers.push(trigger);
                                        updatedEvent = JSON.parse(JSON.stringify(event));
                                    }
                                    return;
                                }
                            }
                        } else if ('point' in event) {
                            const point = (event as any).point;
                            if ('action' in point && point.action.actionUuid === actionUuid) {
                                const existingTrigger = point.action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid);
                                if (!existingTrigger) {
                                    point.action.triggers.push(trigger);
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                }
                                return;
                            } else if ('actions' in point) {
                                const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                                if (action) {
                                    const existingTrigger = action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid);
                                    if (!existingTrigger) {
                                        action.triggers.push(trigger);
                                        updatedEvent = JSON.parse(JSON.stringify(event));
                                    }
                                    return;
                                }
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        removeTrigger: (productId, triggerUuid) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        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) {
                                        point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
                                        updatedEvent = JSON.parse(JSON.stringify(event));
                                    }
                                }
                            }
                        } 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) {
                                    point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                }
                            } 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) {
                                            action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
                                            updatedEvent = JSON.parse(JSON.stringify(event));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        updateTrigger: (productId, triggerUuid, updates) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        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);
                                        updatedEvent = JSON.parse(JSON.stringify(event));
                                        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);
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                    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);
                                            updatedEvent = JSON.parse(JSON.stringify(event));
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        // Renaming functions
        renameProduct: (productId, newName) => {
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    product.productName = newName;
                }
            });
        },

        renameAction: (productId, actionUuid, newName) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        if ('points' in event) {
                            for (const point of (event as ConveyorEventSchema).points) {
                                if (point.action && point.action.actionUuid === actionUuid) {
                                    point.action.actionName = newName;
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                    return;
                                }
                            }
                        } else if ('point' in event) {
                            const point = (event as any).point;
                            if ('action' in point && point.action.actionUuid === actionUuid) {
                                point.action.actionName = newName;
                                updatedEvent = JSON.parse(JSON.stringify(event));
                                return;
                            } else if ('actions' in point) {
                                const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                                if (action) {
                                    action.actionName = newName;
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                    return;
                                }
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        renameTrigger: (productId, triggerUuid, newName) => {
            let updatedEvent: EventsSchema | undefined;
            set((state) => {
                const product = state.products.find(p => p.productId === productId);
                if (product) {
                    for (const event of product.eventDatas) {
                        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) {
                                        trigger.triggerName = newName;
                                        updatedEvent = JSON.parse(JSON.stringify(event));
                                        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) {
                                    trigger.triggerName = newName;
                                    updatedEvent = JSON.parse(JSON.stringify(event));
                                    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) {
                                            trigger.triggerName = newName;
                                            updatedEvent = JSON.parse(JSON.stringify(event));
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            });
            return updatedEvent;
        },

        // Helper functions
        getProductById: (productId) => {
            return get().products.find(p => p.productId === productId);
        },

        getEventByModelUuid: (productId, modelUuid) => {
            const product = get().getProductById(productId);
            if (!product) return undefined;
            return product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
        },

        getPointByUuid: (productId, modelUuid, pointUuid) => {
            const event = get().getEventByModelUuid(productId, modelUuid);
            if (!event) return undefined;

            if ('points' in event) {
                return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
            } else if ('point' in event && (event as any).point.uuid === pointUuid) {
                return (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point;
            }
            return undefined;
        },

        getActionByUuid: (productId, actionUuid) => {
            const product = get().products.find(p => p.productId === productId);
            if (!product) return undefined;

            for (const event of product.eventDatas) {
                if ('points' in event) {
                    for (const point of (event as ConveyorEventSchema).points) {
                        if (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;
        },

        getModelUuidByActionUuid: (productId, actionUuid) => {
            const product = get().products.find(p => p.productId === productId);
            if (!product) return undefined;

            for (const event of product.eventDatas) {
                if ('points' in event) {
                    for (const point of (event as ConveyorEventSchema).points) {
                        if (point.action?.actionUuid === actionUuid) {
                            return event.modelUuid;
                        }
                    }
                } else if ('point' in event) {
                    const point = (event as any).point;
                    if ('action' in point && point.action?.actionUuid === actionUuid) {
                        return event.modelUuid;
                    } else if ('actions' in point) {
                        const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                        if (action) return event.modelUuid;
                    }
                }
            }
            return undefined;
        },

        getPointUuidByActionUuid: (productId, actionUuid) => {
            const product = get().products.find(p => p.productId === productId);
            if (!product) return undefined;

            for (const event of product.eventDatas) {
                if ('points' in event) {
                    for (const point of (event as ConveyorEventSchema).points) {
                        if (point.action?.actionUuid === actionUuid) {
                            return point.uuid;
                        }
                    }
                } else if ('point' in event) {
                    const point = (event as any).point;
                    if ('action' in point && point.action?.actionUuid === actionUuid) {
                        return point.uuid;
                    } else if ('actions' in point) {
                        const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
                        if (action) return point.uuid;
                    }
                }
            }
            return undefined;
        },

        getTriggerByUuid: (productId, triggerUuid) => {
            const product = get().products.find(p => p.productId === productId);
            if (!product) return undefined;

            for (const event of product.eventDatas) {
                if ('points' in event) {
                    for (const point of (event as ConveyorEventSchema).points) {
                        for (const trigger of point.action?.triggers || []) {
                            if (trigger.triggerUuid === triggerUuid) {
                                return trigger;
                            }
                        }
                    }
                } else if ('point' in event) {
                    const point = (event as any).point;
                    if ('action' in point) {
                        for (const trigger of point.action?.triggers || []) {
                            if (trigger.triggerUuid === triggerUuid) {
                                return trigger;
                            }
                        }
                    } else if ('actions' in point) {
                        for (const action of point.actions) {
                            for (const trigger of action.triggers || []) {
                                if (trigger.triggerUuid === triggerUuid) {
                                    return trigger;
                                }
                            }
                        }
                    }
                }
            }
            return undefined;
        },

        getIsEventInProduct: (productId, modelUuid) => {
            const product = get().getProductById(productId);
            if (!product) return false;
            return product.eventDatas.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
        }
    }))
);
