import 'package:sqflite/sqflite.dart'; import 'package:worldhopper/database/database.dart'; import 'package:worldhopper/database/tables/downloaded_chapters_table.dart'; import 'package:worldhopper/models/downloaded_chapter.dart'; import 'package:worldhopper/models/downloaded_series.dart'; /// Repository for downloaded chapters operations class DownloadedChaptersRepository { final DatabaseHelper _dbHelper; DownloadedChaptersRepository(this._dbHelper); /// Get all chapters for a series, ordered by sort_order Future> getChaptersForSeries(String seriesId) async { final db = await _dbHelper.database; final results = await db.query( DownloadedChaptersTable.tableName, where: 'series_id = ?', whereArgs: [seriesId], orderBy: 'sort_order ASC', ); return results.map((row) => DownloadedChapter.fromDatabase(row)).toList(); } /// Get a chapter by server ID and entry ID Future getByEntryId( String serverId, String entryId) async { final db = await _dbHelper.database; final results = await db.query( DownloadedChaptersTable.tableName, where: 'server_id = ? AND entry_id = ?', whereArgs: [serverId, entryId], ); if (results.isEmpty) return null; return DownloadedChapter.fromDatabase(results.first); } /// Get a chapter by ID Future getById(String id) async { final db = await _dbHelper.database; final results = await db.query( DownloadedChaptersTable.tableName, where: 'id = ?', whereArgs: [id], ); if (results.isEmpty) return null; return DownloadedChapter.fromDatabase(results.first); } /// Save or update a downloaded chapter Future save(DownloadedChapter chapter) async { final db = await _dbHelper.database; await db.insert( DownloadedChaptersTable.tableName, chapter.toDatabase(), conflictAlgorithm: ConflictAlgorithm.replace, ); } /// Update the status of a downloaded chapter Future updateStatus(String id, DownloadStatus status, {String? filePath, String? errorMessage}) async { final db = await _dbHelper.database; final updates = { 'status': status.name, 'updated_at': DateTime.now().millisecondsSinceEpoch, }; if (filePath != null) { updates['file_path'] = filePath; } if (errorMessage != null) { updates['error_message'] = errorMessage; } if (status == DownloadStatus.complete) { updates['downloaded_at'] = DateTime.now().millisecondsSinceEpoch; updates['error_message'] = null; } await db.update( DownloadedChaptersTable.tableName, updates, where: 'id = ?', whereArgs: [id], ); } /// Update downloaded pages count for an image stream chapter Future updateDownloadedPages(String id, int downloadedPages) async { final db = await _dbHelper.database; await db.update( DownloadedChaptersTable.tableName, { 'downloaded_pages': downloadedPages, 'updated_at': DateTime.now().millisecondsSinceEpoch, }, where: 'id = ?', whereArgs: [id], ); } /// Delete a chapter by ID Future delete(String id) async { final db = await _dbHelper.database; await db.delete( DownloadedChaptersTable.tableName, where: 'id = ?', whereArgs: [id], ); } /// Delete all chapters for a series Future deleteForSeries(String seriesId) async { final db = await _dbHelper.database; await db.delete( DownloadedChaptersTable.tableName, where: 'series_id = ?', whereArgs: [seriesId], ); } /// Get pending chapters for a series (for resume) Future> getPendingChapters(String seriesId) async { final db = await _dbHelper.database; final results = await db.query( DownloadedChaptersTable.tableName, where: 'series_id = ? AND status IN (?, ?)', whereArgs: [seriesId, 'pending', 'failed'], orderBy: 'sort_order ASC', ); return results.map((row) => DownloadedChapter.fromDatabase(row)).toList(); } }