CREATE TABLE IF NOT EXISTS routes ( id INTEGER PRIMARY KEY AUTOINCREMENT, slug TEXT NOT NULL UNIQUE, creator_id TEXT, name TEXT NOT NULL, description TEXT NOT NULL DEFAULT '', school_name TEXT NOT NULL DEFAULT '', status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'deleted')), gpx_path TEXT NOT NULL, min_lat REAL, min_lon REAL, max_lat REAL, max_lon REAL, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, deleted_at TEXT DEFAULT NULL, activated_at TEXT DEFAULT NULL, trash_path TEXT ) STRICT; CREATE TRIGGER IF NOT EXISTS routes_updated_at AFTER UPDATE ON routes FOR EACH ROW WHEN NEW.updated_at IS OLD.updated_at BEGIN UPDATE routes SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; END; CREATE TABLE IF NOT EXISTS pois ( id INTEGER PRIMARY KEY AUTOINCREMENT, route_id INTEGER NOT NULL REFERENCES routes(id), title TEXT NOT NULL, description TEXT NOT NULL DEFAULT '', lat REAL, lon REAL, trigger_radius_m REAL NOT NULL DEFAULT 80, sequence INTEGER NOT NULL DEFAULT 0, audio_path TEXT, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ) STRICT; CREATE TABLE IF NOT EXISTS poi_images ( id INTEGER PRIMARY KEY AUTOINCREMENT, poi_id INTEGER NOT NULL REFERENCES pois(id), path TEXT NOT NULL, caption TEXT NOT NULL DEFAULT '', sequence INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ) STRICT; CREATE TRIGGER IF NOT EXISTS pois_updated_at AFTER UPDATE ON pois FOR EACH ROW WHEN NEW.updated_at IS OLD.updated_at BEGIN UPDATE pois SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; END; CREATE INDEX IF NOT EXISTS idx_routes_status ON routes(status); CREATE INDEX IF NOT EXISTS idx_routes_activation ON routes(status, activated_at); CREATE INDEX IF NOT EXISTS idx_pois_route ON pois(route_id, sequence); CREATE INDEX IF NOT EXISTS idx_poi_images_poi ON poi_images(poi_id, sequence); CREATE TABLE IF NOT EXISTS collaboration_sessions ( token_hash TEXT PRIMARY KEY NOT NULL, creator_id TEXT NOT NULL, expires_at INTEGER NOT NULL ) STRICT; CREATE TABLE IF NOT EXISTS collaboration_groups ( id TEXT PRIMARY KEY NOT NULL, route_id INTEGER NOT NULL UNIQUE REFERENCES routes(id), source_route_id INTEGER REFERENCES routes(id), owner_creator_id TEXT NOT NULL, code_hash TEXT UNIQUE, code_expires_at INTEGER NOT NULL, active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)), revision INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ) STRICT; CREATE TABLE IF NOT EXISTS collaboration_members ( group_id TEXT NOT NULL REFERENCES collaboration_groups(id) ON DELETE CASCADE, session_hash TEXT NOT NULL REFERENCES collaboration_sessions(token_hash) ON DELETE CASCADE, role TEXT NOT NULL CHECK (role IN ('owner', 'member')), PRIMARY KEY (group_id, session_hash) ) STRICT; CREATE TABLE IF NOT EXISTS collaboration_invitations ( group_id TEXT PRIMARY KEY NOT NULL REFERENCES collaboration_groups(id) ON DELETE CASCADE, code TEXT NOT NULL ) STRICT;