import { useSQLiteContext } from 'expo-sqlite'; // ── Types ────────────────────────────────────────────────────────────────── export type ActivityRow = { id: string; source_hash: string; detail_json: string; timeseries_json: string | null; geojson: string | null; original_path: string | null; synced_at: number | null; origin: 'local' | 'remote'; created_at: number; }; export type ActivitySummary = { id: string; title: string; sport: string; started_at: string; distance_m: number | null; duration_s: number | null; elevation_gain_m: number | null; origin: 'local' | 'remote'; synced_at: number | null; }; // ── Activities ───────────────────────────────────────────────────────────── export function useActivities(): ActivitySummary[] { const db = useSQLiteContext(); // Summaries are derived from the stored detail_json at query time. // JSON extraction via SQLite's json_extract keeps the table schema simple. const rows = db.getAllSync<{ id: string; origin: 'local' | 'remote'; synced_at: number | null; title: string; sport: string; started_at: string; distance_m: number | null; duration_s: number | null; elevation_gain_m: number | null; }>(` SELECT id, origin, synced_at, json_extract(detail_json, '$.title') AS title, json_extract(detail_json, '$.sport') AS sport, json_extract(detail_json, '$.started_at') AS started_at, json_extract(detail_json, '$.distance_m') AS distance_m, json_extract(detail_json, '$.duration_s') AS duration_s, json_extract(detail_json, '$.elevation_gain_m') AS elevation_gain_m FROM activities ORDER BY json_extract(detail_json, '$.started_at') DESC `); return rows; } export function useActivity(id: string): ActivityRow | null { const db = useSQLiteContext(); return db.getFirstSync( 'SELECT * FROM activities WHERE id = ?', [id], ) ?? null; } export async function insertActivity( db: ReturnType, row: Pick, ): Promise { await db.runAsync( `INSERT OR IGNORE INTO activities (id, source_hash, detail_json, timeseries_json, geojson, original_path, origin) VALUES (?, ?, ?, ?, ?, ?, ?)`, [ row.id, row.source_hash, row.detail_json, row.timeseries_json ?? null, row.geojson ?? null, row.original_path ?? null, row.origin, ], ); } export async function upsertRemoteActivity( db: ReturnType, id: string, detailJson: string, ): Promise { const now = Math.floor(Date.now() / 1000); const result = await db.runAsync( `INSERT INTO activities (id, source_hash, detail_json, origin, synced_at) VALUES (?, ?, ?, 'remote', ?) ON CONFLICT(id) DO UPDATE SET detail_json = excluded.detail_json, synced_at = excluded.synced_at WHERE origin = 'remote'`, [id, id, detailJson, now], ); return result.changes > 0; } export async function deleteRemoteActivities( db: ReturnType, ): Promise { const result = await db.runAsync(`DELETE FROM activities WHERE origin = 'remote'`); return result.changes; } export async function deleteActivity( db: ReturnType, id: string, ): Promise { const row = db.getFirstSync<{ original_path: string | null }>( 'SELECT original_path FROM activities WHERE id = ?', [id], ); await db.runAsync('DELETE FROM activities WHERE id = ?', [id]); return row?.original_path ?? null; } export async function deleteActivities( db: ReturnType, ids: string[], ): Promise> { if (ids.length === 0) return []; const rows = db.getAllSync<{ original_path: string | null }>( `SELECT original_path FROM activities WHERE id IN (${ids.map(() => '?').join(',')})`, ids, ); const placeholders = ids.map(() => '?').join(','); await db.runAsync(`DELETE FROM activities WHERE id IN (${placeholders})`, ids); return rows.map(r => r.original_path ?? null); } // ── Settings ─────────────────────────────────────────────────────────────── export async function getSetting( db: ReturnType, key: string, ): Promise { const row = db.getFirstSync<{ value: string }>( 'SELECT value FROM settings WHERE key = ?', [key], ); return row?.value ?? null; } export async function setSetting( db: ReturnType, key: string, value: string, ): Promise { await db.runAsync( `INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`, [key, value], ); } export function useSetting(key: string): string | null { const db = useSQLiteContext(); const row = db.getFirstSync<{ value: string }>( 'SELECT value FROM settings WHERE key = ?', [key], ); return row?.value ?? null; }