insert([ 'operation' => $operation, 'status' => $status, 'metadata' => json_encode($metadata, JSON_THROW_ON_ERROR), 'created_at' => gmdate('Y-m-d H:i:s'), ]); } public function setLastError(string $message): void { Capsule::table('mod_hexagamecloud_installations')->updateOrInsert( ['id' => 1], [ 'last_error' => $message, 'updated_at' => gmdate('Y-m-d H:i:s'), ] ); } public function getLastError(): ?string { $row = Capsule::table('mod_hexagamecloud_installations')->where('id', 1)->first(); return $row?->last_error; } public function updateSyncCursor(?string $cursor): void { Capsule::table('mod_hexagamecloud_sync_cursors')->updateOrInsert( ['id' => 1], [ 'events_cursor' => $cursor, 'last_poll_at' => gmdate('Y-m-d H:i:s'), 'updated_at' => gmdate('Y-m-d H:i:s'), ] ); } public function getSyncCursor(): ?string { $row = Capsule::table('mod_hexagamecloud_sync_cursors')->where('id', 1)->first(); return $row?->events_cursor; } public function storeRemoteEvent(string $remoteId, string $eventType, array $payload, string $status = 'pending'): void { $existing = Capsule::table('mod_hexagamecloud_events') ->where('remote_event_id', $remoteId) ->first(); if ($existing) { return; } Capsule::table('mod_hexagamecloud_events')->insert([ 'remote_event_id' => $remoteId, 'event_type' => $eventType, 'payload' => json_encode($payload, JSON_THROW_ON_ERROR), 'status' => $status, 'created_at' => gmdate('Y-m-d H:i:s'), ]); } public function listLocalEvents(int $limit = 50): array { return Capsule::table('mod_hexagamecloud_events') ->orderBy('id', 'desc') ->limit($limit) ->get() ->map(static fn ($row) => (array) $row) ->all(); } public function countLocalEventsByStatus(string $status): int { return (int) Capsule::table('mod_hexagamecloud_events')->where('status', $status)->count(); } public function getLocalEvent(int $id): ?array { $row = Capsule::table('mod_hexagamecloud_events')->where('id', $id)->first(); return $row ? (array) $row : null; } public function updateLocalEventStatus(int $id, string $status): void { Capsule::table('mod_hexagamecloud_events')->where('id', $id)->update([ 'status' => $status, 'processed_at' => gmdate('Y-m-d H:i:s'), ]); } public function saveReconciliationRun(array $result, string $mode): void { $issues = $result['issues'] ?? []; Capsule::table('mod_hexagamecloud_reconciliation')->insert([ 'run_id' => (string) ($result['runId'] ?? ''), 'mode' => $mode, 'issue_count' => is_array($issues) ? count($issues) : 0, 'payload' => json_encode($result, JSON_THROW_ON_ERROR), 'created_at' => gmdate('Y-m-d H:i:s'), ]); } public function listReconciliationRuns(int $limit = 20): array { return Capsule::table('mod_hexagamecloud_reconciliation') ->orderBy('id', 'desc') ->limit($limit) ->get() ->map(static fn ($row) => (array) $row) ->all(); } }