import { create } from 'zustand' import { v4 as uuidv4 } from 'uuid' import type { SimulationResult } from '@/domain/types' import { simulationRepo } from '@/persistence/repositories' // Excepción arquitectónica documentada: simulation-store importa process-store en una dirección // para suscribirse a cambios de datos y invalidar resultados. No existe dependencia inversa. import { useProcessStore } from '@/store/process-store' interface SimulationState { resultActual: SimulationResult | null // resultado del escenario actual resultAutomated: SimulationResult | null // resultado del escenario automatizado lastSimulatedAt: Date | null // timestamp de la última simulación exitosa isRunning: boolean error: string | null selectedActivityId: string | null // Persiste ambos resultados en IndexedDB y actualiza el estado en memoria. // REGLA: los dos resultados siempre se guardan y actualizan en conjunto. persistResults: (processId: string, actual: SimulationResult, automated: SimulationResult) => Promise setRunning: (running: boolean) => void setError: (error: string | null) => void selectActivity: (bpmnElementId: string | null) => void // Invalida AMBOS resultados a null. Se llama cuando cambian datos del proceso. invalidateResults: () => void reset: () => void } export const useSimulationStore = create((set) => ({ resultActual: null, resultAutomated: null, lastSimulatedAt: null, isRunning: false, error: null, selectedActivityId: null, persistResults: async (processId, actual, automated) => { await simulationRepo.save({ id: uuidv4(), processId, executedAt: Date.now(), result: actual, resultAutomated: automated, }) set({ resultActual: actual, resultAutomated: automated, lastSimulatedAt: new Date(), error: null }) }, setRunning: (isRunning) => set({ isRunning }), setError: (error) => set({ error }), selectActivity: (selectedActivityId) => set({ selectedActivityId }), invalidateResults: () => set({ resultActual: null, resultAutomated: null, lastSimulatedAt: null }), reset: () => set({ resultActual: null, resultAutomated: null, lastSimulatedAt: null, isRunning: false, error: null, selectedActivityId: null, }), })) // Suscripción reactiva: cualquier cambio en activities o currentProcess del process-store // invalida los resultados para garantizar que nunca haya resultados "viejos" visibles. // La comparación por referencia de Zustand asegura que solo fires en cambios reales. useProcessStore.subscribe((state, prevState) => { if ( state.activities !== prevState.activities || state.currentProcess !== prevState.currentProcess ) { useSimulationStore.getState().invalidateResults() } })