import {Database, QueryResult, RunResult, SQLiteValue} from "node-sqlite3-wasm"; import System from "../System.js"; export interface BookActSummariesTable extends Record { act_sum_id: string; book_id: string; user_id: string; act_index: number; last_update: number; summary: string | null; } export interface SyncedActSummaryResult extends Record { act_sum_id: string; book_id: string; last_update: number; } export interface ActQuery extends Record { act_index: number; summary: string; } export default class ActRepository { /** * Fetches all acts for a specific book and user. * @param userId - The unique identifier of the user. * @param bookId - The unique identifier of the book. * @param lang - The language for error messages ('fr' or 'en'). * @returns An array of ActQuery objects containing act index and summary. * @throws Error if the database operation fails. */ public static fetchAllActs(userId: string, bookId: string, lang: 'fr' | 'en'): ActQuery[] { try { const db: Database = System.getDb(); const query: string = 'SELECT act_index, summary FROM book_act_summaries WHERE book_id=? AND user_id=?'; const params: SQLiteValue[] = [bookId, userId]; return db.all(query, params) as ActQuery[]; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer les actes.` : `Unable to retrieve acts.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Updates the summary of an existing act. * @param userId - The unique identifier of the user. * @param bookId - The unique identifier of the book. * @param actId - The unique identifier of the act summary. * @param summary - The new summary text. * @param lastUpdate - The timestamp of the last update in seconds. * @param lang - The language for error messages ('fr' or 'en'). * @returns True if the update was successful, false otherwise. * @throws Error if the database operation fails. */ public static updateActSummary(userId: string, bookId: string, actId: number, summary: string, lastUpdate: number, lang: 'fr' | 'en'): boolean { try { const db: Database = System.getDb(); const query: string = 'UPDATE book_act_summaries SET summary=?, last_update=? WHERE user_id=? AND book_id=? AND act_sum_id=?'; const params: SQLiteValue[] = [summary, lastUpdate, userId, bookId, actId]; const updateResult: RunResult = db.run(query, params); return updateResult.changes > 0; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de mettre à jour le résumé de l'acte.` : `Unable to update act summary.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Inserts a new act summary into the database. * @param actSummaryId - The unique identifier for the new act summary. * @param userId - The unique identifier of the user. * @param bookId - The unique identifier of the book. * @param actId - The act index number. * @param actSummary - The summary text for the act. * @param lang - The language for error messages ('fr' or 'en'). * @returns The act summary ID if insertion was successful. * @throws Error if the database operation fails. */ static insertActSummary(actSummaryId: string, userId: string, bookId: string, actId: number, actSummary: string, lang: 'fr' | 'en'): string { let insertResult: RunResult; try { const db: Database = System.getDb(); const query: string = 'INSERT INTO book_act_summaries (act_sum_id, book_id, user_id, act_index, summary, last_update) VALUES (?,?,?,?,?,?)'; const params: SQLiteValue[] = [actSummaryId, bookId, userId, actId, actSummary, System.timeStampInSeconds()]; insertResult = db.run(query, params); } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible d'ajouter le résumé de l'acte.` : `Unable to add act summary.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } if (!insertResult) { throw new Error(lang === 'fr' ? `Erreur lors de l'ajout du résumé de l'acte.` : `Error adding act summary.`); } return actSummaryId; } /** * Fetches all act summaries for a specific book. * @param userId - The unique identifier of the user. * @param bookId - The unique identifier of the book. * @param lang - The language for error messages ('fr' or 'en'). * @returns A promise resolving to an array of BookActSummariesTable objects. * @throws Error if the database operation fails. */ static async fetchBookActSummaries(userId: string, bookId: string, lang: 'fr' | 'en'): Promise { try { const db: Database = System.getDb(); const query: string = 'SELECT act_sum_id, book_id, user_id, act_index, summary, last_update FROM book_act_summaries WHERE user_id=? AND book_id=?'; const params: SQLiteValue[] = [userId, bookId]; return db.all(query, params) as BookActSummariesTable[]; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer les résumés des actes.` : `Unable to retrieve act summaries.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Fetches all synced act summaries for a user. * @param userId - The unique identifier of the user. * @param lang - The language for error messages ('fr' or 'en'). * @returns An array of SyncedActSummaryResult objects containing sync metadata. * @throws Error if the database operation fails. */ static fetchSyncedActSummaries(userId: string, lang: 'fr' | 'en'): SyncedActSummaryResult[] { try { const db: Database = System.getDb(); const query: string = 'SELECT act_sum_id, book_id, last_update FROM book_act_summaries WHERE user_id = ?'; const params: SQLiteValue[] = [userId]; const syncedActSummaries: SyncedActSummaryResult[] = db.all(query, params) as SyncedActSummaryResult[]; return syncedActSummaries; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer les résumés d'actes synchronisés.` : `Unable to retrieve synced act summaries.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Inserts a synced act summary from remote data. * @param actSumId - The unique identifier of the act summary. * @param bookId - The unique identifier of the book. * @param userId - The unique identifier of the user. * @param actIndex - The act index number. * @param summary - The summary text (can be null). * @param lastUpdate - The timestamp of the last update in seconds. * @param lang - The language for error messages ('fr' or 'en'). * @returns True if the insertion was successful, false otherwise. * @throws Error if the database operation fails. */ static insertSyncActSummary(actSumId: string, bookId: string, userId: string, actIndex: number, summary: string | null, lastUpdate: number, lang: 'fr' | 'en'): boolean { try { const db: Database = System.getDb(); const query: string = 'INSERT INTO book_act_summaries (act_sum_id, book_id, user_id, act_index, summary, last_update) VALUES (?, ?, ?, ?, ?, ?)'; const params: SQLiteValue[] = [actSumId, bookId, userId, actIndex, summary, lastUpdate]; const insertResult: RunResult = db.run(query, params); return insertResult.changes > 0; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible d'insérer le résumé d'acte.` : `Unable to insert act summary.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Fetches a complete act summary by its unique identifier. * @param id - The unique identifier of the act summary. * @param lang - The language for error messages ('fr' or 'en'). * @returns A promise resolving to an array of BookActSummariesTable objects. * @throws Error if the database operation fails. */ static async fetchCompleteActSummaryById(id: string, lang: "fr" | "en"): Promise { try { const db: Database = System.getDb(); const query: string = `SELECT act_sum_id, book_id, user_id, act_index, summary, last_update FROM book_act_summaries WHERE act_sum_id = ?`; const params: SQLiteValue[] = [id]; const actSummary: BookActSummariesTable[] = db.all(query, params) as BookActSummariesTable[]; return actSummary; } catch (error: unknown) { if (error instanceof Error) { throw new Error(lang === 'fr' ? `Impossible de récupérer le résumé d'acte complet.` : `Unable to retrieve complete act summary.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Checks if an act summary exists for a given user, book, and act index. * @param userId - The unique identifier of the user. * @param bookId - The unique identifier of the book. * @param actIndex - The act index number to check. * @param lang - The language for error messages ('fr' or 'en'). * @returns True if the act summary exists, false otherwise. * @throws Error if the database operation fails. */ static actSummarizeExist(userId: string, bookId: string, actIndex: number, lang: "fr" | "en"): boolean { try { const db: Database = System.getDb(); const query: string = 'SELECT 1 FROM book_act_summaries WHERE user_id =? AND book_id =? AND act_index = ?'; const params: SQLiteValue[] = [userId, bookId, actIndex]; const existenceCheck: QueryResult | null = db.get(query, params) || null; return existenceCheck !== null; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de vérifier l'existence du résumé de l'acte.` : `Unable to check act summary existence.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } }