export function createInMemoryHealthObservationStore() { const rowsByUser = new Map(); const dedupIndex = new Map(); let nextId = 1; return { listUserIds() { return [...rowsByUser.keys()]; }, async list(userId, { limit = 50 } = {}) { const rows = rowsByUser.get(String(userId)) ?? []; return rows.filter((row) => row.deletedAt == null).slice(0, limit); }, async findByDedupKey(userId, dedupKey) { const id = dedupIndex.get(`${String(userId)}|${dedupKey}`); if (!id) return null; const rows = rowsByUser.get(String(userId)) ?? []; return rows.find((row) => row.id === id) ?? null; }, async insert(userId, observation) { if (!observation?.confirmed) { const error = Object.assign(new Error('健康观测必须确认后才能保存'), { code: 'health_unconfirmed', }); throw error; } const row = { id: nextId++, userId: String(userId), observedAt: observation.observedAt, metricType: observation.metricType, valueNum: observation.valueNum ?? null, valueText: observation.valueText ?? null, unit: observation.unit ?? null, context: observation.context ?? null, source: observation.source ?? 'manual', sourceRef: observation.sourceRef ?? null, qualityFlag: observation.qualityFlag ?? 'ok', deletedAt: observation.deletedAt ?? null, note: observation.note ?? null, createdAt: observation.createdAt ?? Date.now(), }; if (observation.dedupKey) { dedupIndex.set(`${row.userId}|${observation.dedupKey}`, row.id); } const list = rowsByUser.get(row.userId) ?? []; list.unshift(row); rowsByUser.set(row.userId, list); return row; }, }; }