const config = require("../config/index"); const { formatDate } = require("../utils/date"); const { safeGetStorage, safeSetStorage } = require("../utils/storage"); const { normalizeRegionArray, deriveRegionFromParts, getRegionParts } = require("../utils/region"); const STORAGE_KEYS = { history: "fortune:history", quotaPrefix: "fortune:quota:", form: "fortune:form" }; function createDefaultForm() { return { birthDate: formatDate(new Date()), birthTime: "", birthProvince: "", birthCity: "", birthDistrict: "", birthRegion: [] }; } function normalizeForm(payload, fallback) { const base = fallback || createDefaultForm(); const toStringValue = (value, fallbackValue = "") => (typeof value === "string" ? value : fallbackValue); const normalized = { birthDate: toStringValue(payload && payload.birthDate, base.birthDate), birthTime: toStringValue(payload && payload.birthTime, base.birthTime || ""), birthProvince: toStringValue(payload && payload.birthProvince, base.birthProvince || ""), birthCity: toStringValue(payload && payload.birthCity, base.birthCity || ""), birthDistrict: toStringValue(payload && payload.birthDistrict, base.birthDistrict || ""), birthRegion: [] }; const persistedRegion = normalizeRegionArray(payload && payload.birthRegion); const baseRegion = normalizeRegionArray(base.birthRegion); if (persistedRegion.length) { normalized.birthRegion = persistedRegion; } else if (baseRegion.length) { normalized.birthRegion = baseRegion; } else { normalized.birthRegion = deriveRegionFromParts({ province: normalized.birthProvince, city: normalized.birthCity, district: normalized.birthDistrict }); } const parts = getRegionParts(normalized.birthRegion, { province: normalized.birthProvince, city: normalized.birthCity, district: normalized.birthDistrict }); normalized.birthProvince = parts.province; normalized.birthCity = parts.city; normalized.birthDistrict = parts.district; return normalized; } function loadPersistedForm() { const stored = safeGetStorage(STORAGE_KEYS.form, null); if (stored && typeof stored === "object") { return normalizeForm(stored); } const defaults = createDefaultForm(); safeSetStorage(STORAGE_KEYS.form, defaults); return defaults; } function persistForm(form) { const normalized = normalizeForm(form); safeSetStorage(STORAGE_KEYS.form, normalized); } const state = { form: loadPersistedForm(), currentFortune: null, history: [], quota: { date: "", count: 0 }, lastError: "" }; function getQuotaStorageKey(dateStr) { return `${STORAGE_KEYS.quotaPrefix}${dateStr.replace(/-/g, "")}`; } function syncQuota() { const today = formatDate(new Date()); const storageKey = getQuotaStorageKey(today); const stored = safeGetStorage(storageKey, 0); const count = typeof stored === "number" ? stored : 0; state.quota = { date: today, count }; } function incrementQuota() { const today = formatDate(new Date()); if (state.quota.date !== today) { syncQuota(); } const nextCount = state.quota.count + 1; state.quota = { date: today, count: nextCount }; safeSetStorage(getQuotaStorageKey(today), nextCount); } function canGenerateToday() { const today = formatDate(new Date()); if (state.quota.date !== today) { syncQuota(); } return state.quota.count < config.maxDailyQuota; } function loadHistory() { const stored = safeGetStorage(STORAGE_KEYS.history, []); state.history = Array.isArray(stored) ? stored : []; } function saveHistory() { safeSetStorage(STORAGE_KEYS.history, state.history); } function appendHistory(formSnapshot, fortune) { const snapshot = normalizeForm(formSnapshot, state.form); const entry = { id: `${Date.now()}_${Math.random().toString(36).slice(2, 6)}`, createdAt: new Date().toISOString(), formSnapshot: snapshot, fortune }; const next = [entry, ...state.history]; state.history = next.slice(0, config.historyLimit); saveHistory(); return entry; } function getHistoryById(id) { return state.history.find((item) => item.id === id); } function setForm(partial) { const merged = Object.assign({}, state.form, partial); state.form = normalizeForm(merged, state.form); persistForm(state.form); } function setCurrentFortune(fortune) { state.currentFortune = fortune; } function getState() { return state; } function initStore() { syncQuota(); loadHistory(); } module.exports = { initStore, getState, setForm, setCurrentFortune, appendHistory, loadHistory, getHistoryById, canGenerateToday, incrementQuota };