import { randomUUID } from "node:crypto"; import { getPool } from "../db/pool"; const DEFAULT_SETTINGS = { volume: 80, language: "id-ID", heartbeat_interval_seconds: 60 }; function nowIso() { return new Date().toISOString(); } function mapConfig(row) { return { device_id: row.device_id, config_version: Number(row.config_version), settings_json: row.settings_json || {}, updated_at: row.updated_at }; } function mapAck(row) { return { id: row.id, device_id: row.device_id, config_version: Number(row.config_version), status: row.status, reason: row.reason || undefined, payload_json: row.payload_json || {}, acked_at: row.acked_at }; } export async function getDeviceConfig(deviceId) { const { rows } = await getPool().query("SELECT * FROM device_configs WHERE device_id = $1", [deviceId]); return rows[0] ? mapConfig(rows[0]) : null; } export async function getOrCreateDeviceConfig(deviceId) { const existing = await getDeviceConfig(deviceId); if (existing) { return existing; } return upsertDeviceConfig({ device_id: deviceId, settings_json: DEFAULT_SETTINGS }); } export async function upsertDeviceConfig(payload) { const existing = await getDeviceConfig(payload.device_id); const nextVersion = payload.config_version || (existing ? existing.config_version + 1 : 1); const { rows } = await getPool().query(`INSERT INTO device_configs (device_id, config_version, settings_json, updated_at) VALUES ($1,$2,$3,$4) ON CONFLICT (device_id) DO UPDATE SET config_version = EXCLUDED.config_version, settings_json = EXCLUDED.settings_json, updated_at = EXCLUDED.updated_at RETURNING *`, [payload.device_id, nextVersion, payload.settings_json, nowIso()]); return mapConfig(rows[0]); } export async function createDeviceConfigAck(payload) { const { rows } = await getPool().query(`INSERT INTO device_config_acks ( id, device_id, config_version, status, reason, payload_json, acked_at ) VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING *`, [ `cfgack_${randomUUID()}`, payload.device_id, payload.config_version, payload.status, payload.reason || null, payload.payload_json || {}, nowIso() ]); return mapAck(rows[0]); } export async function listDeviceConfigAcks(deviceId, limit = 50) { const { rows } = await getPool().query(`SELECT * FROM device_config_acks WHERE device_id = $1 ORDER BY acked_at DESC LIMIT $2`, [deviceId, Math.min(Math.max(limit, 1), 200)]); return rows.map(mapAck); } export function toDeviceConfigPayload(config) { return { ...config }; } export function toDeviceConfigAckPayload(ack) { return { ...ack }; }