import { computed, onUnmounted, ref } from "vue"; const pad2 = (value) => value.toString().padStart(2, "0"); export function useWashProgress(options) { const { storageKey = "mywash_progress_v6", expirationMs = 2 * 60 * 60 * 1000, currentStep, washInProgress, washLaneId, washStartTime, licensePlateInput, vehicleTypeSelect, radioWashType, radioLaneOption, customerNumberInput, answers, completedTasks, nearestDepartmentId, forceNearestDepartmentEvaluationId, isForcingNearestDepartment, applyRestoredState, } = options; const isRestoring = ref(true); const isDestroying = ref(false); const isDestroyingManual = ref(false); const completedDurationMs = ref(null); const now = ref(Date.now()); let timerInterval = null; let isDestroyingGlobal = false; let beforeUnloadHandler = null; const timeSinceWashStart = computed(() => { if (washInProgress.value && washStartTime.value) { return now.value - washStartTime.value; } return 0; }); const formattedElapsed = computed(() => { const totalSeconds = Math.floor(timeSinceWashStart.value / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; if (minutes < 0 || seconds < 0) { return "00:00"; } return `${pad2(minutes)}:${pad2(seconds)}`; }); const loadProgress = () => { try { const raw = localStorage.getItem(storageKey); if (!raw) { return null; } return JSON.parse(raw); } catch (error) { console.warn("Failed to load wash progress:", error); return null; } }; const clearProgress = () => { try { localStorage.removeItem(storageKey); } catch {} }; const saveProgress = (trigger = "manual") => { if (isRestoring.value) { return; } if (isDestroying.value || isDestroyingManual.value || isDestroyingGlobal) { if (trigger !== "beforeunload") { return; } } if ( washInProgress.value && currentStep.value === 0 && trigger !== "onStartWash" && trigger !== "onCloseCompleted" ) { return; } if (!washInProgress.value && Number(currentStep.value) === 5) { clearProgress(); return; } try { const payload = { washInProgress: washInProgress.value, washLaneId: washLaneId.value, washStartTime: washStartTime.value, currentStep: currentStep.value, licensePlateInput: licensePlateInput.value, vehicleTypeSelect: vehicleTypeSelect.value, radioWashType: radioWashType.value, radioLaneOption: radioLaneOption.value, customerNumberInput: customerNumberInput.value, answers: answers.value, completedTasks: completedTasks.value, nearestDepartmentId: nearestDepartmentId(), forceNearestDepartmentEvaluationId: forceNearestDepartmentEvaluationId.value, savedAt: Date.now(), isForcingNearestDepartment: isForcingNearestDepartment.value, }; localStorage.setItem(storageKey, JSON.stringify(payload)); } catch (error) { console.warn("Failed to save wash progress:", error); } }; const startElapsedTimer = () => { if (timerInterval) { clearInterval(timerInterval); } timerInterval = setInterval(() => { now.value = Date.now(); if (washInProgress.value) { saveProgress("timer"); } }, 1000); }; const stopElapsedTimer = () => { if (timerInterval) { clearInterval(timerInterval); timerInterval = null; } }; const markDestroying = () => { isDestroyingGlobal = true; isDestroyingManual.value = true; isDestroying.value = true; }; const restoreProgress = () => { const savedProgress = loadProgress(); if (!savedProgress) { isRestoring.value = false; return null; } const timeDiff = Date.now() - (savedProgress.savedAt || 0); if (timeDiff >= expirationMs) { clearProgress(); isRestoring.value = false; return null; } applyRestoredState(savedProgress); if (washInProgress.value) { startElapsedTimer(); } const restoredStep = savedProgress.currentStep; const isSameRestoredProgress = () => ( Boolean(washInProgress.value) === Boolean(savedProgress.washInProgress) && String(washLaneId.value ?? "") === String(savedProgress.washLaneId ?? "") && String(washStartTime.value ?? "") === String(savedProgress.washStartTime ?? "") && String(licensePlateInput.value ?? "") === String(savedProgress.licensePlateInput ?? "") && String(vehicleTypeSelect.value ?? "") === String(savedProgress.vehicleTypeSelect ?? "") && String(radioLaneOption.value ?? "") === String(savedProgress.radioLaneOption ?? "") ); setTimeout(() => { if (isSameRestoredProgress() && currentStep.value !== restoredStep) { currentStep.value = restoredStep; } isRestoring.value = false; }, 1500); return savedProgress; }; const registerBeforeUnload = () => { if (typeof window === "undefined") { return () => {}; } beforeUnloadHandler = () => { markDestroying(); saveProgress("beforeunload"); }; window.addEventListener("beforeunload", beforeUnloadHandler); return () => { if (beforeUnloadHandler) { window.removeEventListener("beforeunload", beforeUnloadHandler); beforeUnloadHandler = null; } }; }; const cleanup = () => { markDestroying(); stopElapsedTimer(); if (typeof window !== "undefined" && beforeUnloadHandler) { window.removeEventListener("beforeunload", beforeUnloadHandler); beforeUnloadHandler = null; } }; onUnmounted(() => { cleanup(); }); return { completedDurationMs, now, isRestoring, isDestroying, isDestroyingManual, timeSinceWashStart, formattedElapsed, loadProgress, saveProgress, clearProgress, restoreProgress, startElapsedTimer, stopElapsedTimer, markDestroying, registerBeforeUnload, cleanup, }; }