import { Database, RunResult, SQLiteValue } from "node-sqlite3-wasm"; import System from "@/electron/database/System"; export interface BookAIGuideLineTable extends Record { user_id: string; book_id: string; global_resume: string | null; themes: string | null; verbe_tense: number | null; narrative_type: number | null; langue: number | null; dialogue_type: number | null; tone: string | null; atmosphere: string | null; current_resume: string | null; last_update: number; } export interface BookGuideLineTable extends Record { user_id: string; book_id: string; tone: string | null; atmosphere: string | null; writing_style: string | null; themes: string | null; symbolism: string | null; motifs: string | null; narrative_voice: string | null; pacing: string | null; intended_audience: string | null; key_messages: string | null; last_update: number; } export interface SyncedGuideLineResult extends Record { book_id: string; last_update: number; } export interface SyncedAIGuideLineResult extends Record { book_id: string; last_update: number; } export interface GuideLineQuery extends Record { tone: string; atmosphere: string; writing_style: string; themes: string; symbolism: string; motifs: string; narrative_voice: string; pacing: string; intended_audience: string; key_messages: string; } export interface GuideLineAIQuery extends Record { user_id: string; book_id: string; global_resume: string | null; themes: string | null; verbe_tense: number | null; narrative_type: number | null; langue: number | null; dialogue_type: number | null; tone: string | null; atmosphere: string | null; current_resume: string | null; meta: string; } export default class GuidelineRepo { /** * Fetches the guideline for a specific book. * @param userId - The user identifier * @param bookId - The book identifier * @param lang - The language for error messages ('fr' or 'en') * @returns An array of guideline query results * @throws Error if the guideline cannot be retrieved */ public static fetchGuideLine(userId: string, bookId: string, lang: 'fr' | 'en'): GuideLineQuery[] { let guidelines: GuideLineQuery[]; try { const db: Database = System.getDb(); const query: string = 'SELECT * FROM book_guide_line WHERE book_id=? AND user_id=?'; const params: SQLiteValue[] = [bookId, userId]; guidelines = db.all(query, params) as GuideLineQuery[]; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer la ligne directrice.` : `Unable to retrieve guideline.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } return guidelines; } /** * Updates or inserts a guideline for a specific book. * If the guideline exists, it updates it; otherwise, it inserts a new one. * @param userId - The user identifier * @param bookId - The book identifier * @param encryptedTone - The encrypted tone value * @param encryptedAtmosphere - The encrypted atmosphere value * @param encryptedWritingStyle - The encrypted writing style value * @param encryptedThemes - The encrypted themes value * @param encryptedSymbolism - The encrypted symbolism value * @param encryptedMotifs - The encrypted motifs value * @param encryptedNarrativeVoice - The encrypted narrative voice value * @param encryptedPacing - The encrypted pacing value * @param encryptedKeyMessages - The encrypted key messages value * @param encryptedIntendedAudience - The encrypted intended audience value * @param lang - The language for error messages ('fr' or 'en') * @returns True if the operation was successful * @throws Error if the guideline cannot be updated or inserted */ static updateGuideLine( userId: string, bookId: string, encryptedTone: string, encryptedAtmosphere: string, encryptedWritingStyle: string, encryptedThemes: string, encryptedSymbolism: string, encryptedMotifs: string, encryptedNarrativeVoice: string, encryptedPacing: string, encryptedKeyMessages: string, encryptedIntendedAudience: string, lang: 'fr' | 'en' ): boolean { try { const db: Database = System.getDb(); const updateQuery: string = 'UPDATE book_guide_line SET tone=?, atmosphere=?, writing_style=?, themes=?, symbolism=?, motifs=?, narrative_voice=?, pacing=?, key_messages=?, last_update=? WHERE user_id=? AND book_id=?'; const updateParams: SQLiteValue[] = [ encryptedTone, encryptedAtmosphere, encryptedWritingStyle, encryptedThemes, encryptedSymbolism, encryptedMotifs, encryptedNarrativeVoice, encryptedPacing, encryptedKeyMessages, System.timeStampInSeconds(), userId, bookId ]; const updateResult: RunResult = db.run(updateQuery, updateParams); if (updateResult.changes > 0) { return true; } else { const insertQuery: string = 'INSERT INTO book_guide_line (user_id, book_id, tone, atmosphere, writing_style, themes, symbolism, motifs, narrative_voice, pacing, intended_audience, key_messages, last_update) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)'; const insertParams: SQLiteValue[] = [ userId, bookId, encryptedTone, encryptedAtmosphere, encryptedWritingStyle, encryptedThemes, encryptedSymbolism, encryptedMotifs, encryptedNarrativeVoice, encryptedPacing, encryptedIntendedAudience, encryptedKeyMessages, System.timeStampInSeconds() ]; const insertResult: RunResult = db.run(insertQuery, insertParams); return insertResult.changes > 0; } } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de mettre à jour la ligne directrice.` : `Unable to update guideline.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Inserts or updates an AI guideline for a specific book. * If the AI guideline exists, it updates it; otherwise, it inserts a new one. * @param userId - The user identifier * @param bookId - The book identifier * @param narrativeType - The narrative type identifier * @param dialogueType - The dialogue type identifier * @param encryptedPlotSummary - The encrypted plot summary * @param encryptedToneAtmosphere - The encrypted tone and atmosphere value * @param verbTense - The verb tense identifier * @param language - The language identifier * @param encryptedThemes - The encrypted themes value * @param lang - The language for error messages ('fr' or 'en') * @returns True if the operation was successful * @throws Error if the AI guideline cannot be inserted or updated */ static insertAIGuideLine( userId: string, bookId: string, narrativeType: number, dialogueType: number, encryptedPlotSummary: string, encryptedToneAtmosphere: string, verbTense: number, language: number, encryptedThemes: string, lang: 'fr' | 'en' ): boolean { try { const db: Database = System.getDb(); const updateQuery: string = 'UPDATE book_ai_guide_line SET narrative_type=?, dialogue_type=?, global_resume=?, atmosphere=?, verbe_tense=?, langue=?, themes=?, last_update=? WHERE user_id=? AND book_id=?'; const updateParams: SQLiteValue[] = [ narrativeType ? narrativeType : null, dialogueType ? dialogueType : null, encryptedPlotSummary, encryptedToneAtmosphere, verbTense ? verbTense : null, language ? language : null, encryptedThemes, System.timeStampInSeconds(), userId, bookId ]; const updateResult: RunResult = db.run(updateQuery, updateParams); if (updateResult.changes > 0) { return true; } else { const insertQuery: string = 'INSERT INTO book_ai_guide_line (user_id, book_id, global_resume, themes, verbe_tense, narrative_type, langue, dialogue_type, tone, atmosphere, current_resume, last_update) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'; const insertParams: SQLiteValue[] = [ userId, bookId, encryptedPlotSummary, encryptedThemes, verbTense ? verbTense : null, narrativeType ? narrativeType : null, language ? language : null, dialogueType ? dialogueType : null, encryptedToneAtmosphere, encryptedToneAtmosphere, encryptedPlotSummary, System.timeStampInSeconds() ]; const insertResult: RunResult = db.run(insertQuery, insertParams); 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 la ligne directrice IA.` : `Unable to insert AI guideline.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Fetches the AI guideline for a specific book. * @param userId - The user identifier * @param bookId - The book identifier * @param lang - The language for error messages ('fr' or 'en') * @returns The AI guideline query result * @throws Error if the AI guideline cannot be retrieved or is not found */ static fetchGuideLineAI(userId: string, bookId: string, lang: 'fr' | 'en'): GuideLineAIQuery { let aiGuideline: GuideLineAIQuery | null; try { const db: Database = System.getDb(); const query: string = 'SELECT narrative_type, dialogue_type, global_resume, atmosphere, verbe_tense, langue, themes, current_resume FROM book_ai_guide_line WHERE user_id=? AND book_id=?'; const params: SQLiteValue[] = [userId, bookId]; aiGuideline = db.get(query, params) as GuideLineAIQuery | null; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer la ligne directrice IA.` : `Unable to retrieve AI guideline.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } if (!aiGuideline) { throw new Error(lang === 'fr' ? `Ligne directrice IA non trouvée.` : `AI guideline not found.`); } return aiGuideline; } /** * Fetches the book AI guideline table data for a specific book. * @param userId - The user identifier * @param bookId - The book identifier * @param lang - The language for error messages ('fr' or 'en') * @returns A promise resolving to an array of book AI guideline table entries * @throws Error if the AI guideline cannot be retrieved */ static async fetchBookAIGuideLine(userId: string, bookId: string, lang: 'fr' | 'en'): Promise { try { const db: Database = System.getDb(); const query: string = 'SELECT user_id, book_id, global_resume, themes, verbe_tense, narrative_type, langue, dialogue_type, tone, atmosphere, current_resume, last_update FROM book_ai_guide_line WHERE user_id=? AND book_id=?'; const params: SQLiteValue[] = [userId, bookId]; const aiGuidelines: BookAIGuideLineTable[] = db.all(query, params) as BookAIGuideLineTable[]; return aiGuidelines; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer la ligne directrice IA.` : `Unable to retrieve AI guideline.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Fetches the book guideline table data for a specific book. * @param userId - The user identifier * @param bookId - The book identifier * @param lang - The language for error messages ('fr' or 'en') * @returns A promise resolving to an array of book guideline table entries * @throws Error if the guideline cannot be retrieved */ static async fetchBookGuideLineTable(userId: string, bookId: string, lang: 'fr' | 'en'): Promise { try { const db: Database = System.getDb(); const query: string = 'SELECT user_id, book_id, tone, atmosphere, writing_style, themes, symbolism, motifs, narrative_voice, pacing, intended_audience, key_messages, last_update FROM book_guide_line WHERE user_id=? AND book_id=?'; const params: SQLiteValue[] = [userId, bookId]; const guidelines: BookGuideLineTable[] = db.all(query, params) as BookGuideLineTable[]; return guidelines; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer la ligne directrice.` : `Unable to retrieve guideline.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Fetches all synced guidelines for a specific user. * @param userId - The user identifier * @param lang - The language for error messages ('fr' or 'en') * @returns An array of synced guideline results containing book_id and last_update * @throws Error if the synced guidelines cannot be retrieved */ static fetchSyncedGuideLine(userId: string, lang: 'fr' | 'en'): SyncedGuideLineResult[] { try { const db: Database = System.getDb(); const query: string = 'SELECT book_id, last_update FROM book_guide_line WHERE user_id = ?'; const params: SQLiteValue[] = [userId]; const syncedGuidelines: SyncedGuideLineResult[] = db.all(query, params) as SyncedGuideLineResult[]; return syncedGuidelines; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer les lignes directrices synchronisées.` : `Unable to retrieve synced guidelines.`); } else { console.error("An unknown error occurred."); throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Fetches all synced AI guidelines for a specific user. * @param userId - The user identifier * @param lang - The language for error messages ('fr' or 'en') * @returns An array of synced AI guideline results containing book_id and last_update * @throws Error if the synced AI guidelines cannot be retrieved */ static fetchSyncedAIGuideLine(userId: string, lang: 'fr' | 'en'): SyncedAIGuideLineResult[] { try { const db: Database = System.getDb(); const query: string = 'SELECT book_id, last_update FROM book_ai_guide_line WHERE user_id = ?'; const params: SQLiteValue[] = [userId]; const syncedAIGuidelines: SyncedAIGuideLineResult[] = db.all(query, params) as SyncedAIGuideLineResult[]; return syncedAIGuidelines; } catch (error: unknown) { if (error instanceof Error) { console.error(`DB Error: ${error.message}`); throw new Error(lang === 'fr' ? `Impossible de récupérer les lignes directrices IA synchronisées.` : `Unable to retrieve synced AI guidelines.`); } 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 AI guideline for a specific book. * @param userId - The user identifier * @param bookId - The book identifier * @param globalResume - The global resume value (nullable) * @param themes - The themes value (nullable) * @param verbeTense - The verb tense identifier (nullable) * @param narrativeType - The narrative type identifier (nullable) * @param langue - The language identifier (nullable) * @param dialogueType - The dialogue type identifier (nullable) * @param tone - The tone value (nullable) * @param atmosphere - The atmosphere value (nullable) * @param currentResume - The current resume value (nullable) * @param lastUpdate - The last update timestamp * @param lang - The language for error messages ('fr' or 'en') * @returns True if the insertion was successful * @throws Error if the AI guideline cannot be inserted */ static insertSyncAIGuideLine( userId: string, bookId: string, globalResume: string | null, themes: string | null, verbeTense: number | null, narrativeType: number | null, langue: number | null, dialogueType: number | null, tone: string | null, atmosphere: string | null, currentResume: string | null, lastUpdate: number, lang: 'fr' | 'en' ): boolean { try { const db: Database = System.getDb(); const query: string = `INSERT INTO book_ai_guide_line (user_id, book_id, global_resume, themes, verbe_tense, narrative_type, langue, dialogue_type, tone, atmosphere, current_resume, last_update) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; const params: SQLiteValue[] = [ userId, bookId, globalResume, themes, verbeTense, narrativeType, langue, dialogueType, tone, atmosphere, currentResume, 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 la ligne directrice IA.` : `Unable to insert AI guideline.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } /** * Inserts a synced guideline for a specific book. * @param userId - The user identifier * @param bookId - The book identifier * @param tone - The tone value (nullable) * @param atmosphere - The atmosphere value (nullable) * @param writingStyle - The writing style value (nullable) * @param themes - The themes value (nullable) * @param symbolism - The symbolism value (nullable) * @param motifs - The motifs value (nullable) * @param narrativeVoice - The narrative voice value (nullable) * @param pacing - The pacing value (nullable) * @param intendedAudience - The intended audience value (nullable) * @param keyMessages - The key messages value (nullable) * @param lastUpdate - The last update timestamp * @param lang - The language for error messages ('fr' or 'en') * @returns True if the insertion was successful * @throws Error if the guideline cannot be inserted */ static insertSyncGuideLine( userId: string, bookId: string, tone: string | null, atmosphere: string | null, writingStyle: string | null, themes: string | null, symbolism: string | null, motifs: string | null, narrativeVoice: string | null, pacing: string | null, intendedAudience: string | null, keyMessages: string | null, lastUpdate: number, lang: 'fr' | 'en' ): boolean { try { const db: Database = System.getDb(); const query: string = `INSERT INTO book_guide_line (user_id, book_id, tone, atmosphere, writing_style, themes, symbolism, motifs, narrative_voice, pacing, intended_audience, key_messages, last_update) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; const params: SQLiteValue[] = [ userId, bookId, tone, atmosphere, writingStyle, themes, symbolism, motifs, narrativeVoice, pacing, intendedAudience, keyMessages, 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 la ligne directrice.` : `Unable to insert guideline.`); } else { throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred."); } } } }