import type { IpcMainInvokeEvent } from 'electron';
import { getSecureStorage } from '../storage/SecureStorage.js';

// ============================================================
// SESSION MANAGEMENT - Auto-inject userId and lang
// ============================================================

/**
 * Get userId from secure storage (OS-encrypted)
 * Set during login via 'login-success' event
 */
function getUserIdFromSession(): string | null {
    const storage = getSecureStorage();
    return storage.get<string>('userId', null);
}

/**
 * Get lang from secure storage
 * Set via 'set-lang' handler, defaults to 'fr'
 */
function getLangFromSession(): 'fr' | 'en' {
    const storage = getSecureStorage();
    return storage.get<'fr' | 'en'>('userLang', 'fr') as 'fr' | 'en';
}

// ============================================================
// UNIVERSAL HANDLER - Like a Fastify route
// Automatically injects: userId, lang
// Optional body parameter (for GET, POST, PUT, DELETE)
// Generic return type (void, object, etc.)
// ============================================================

/**
 * Universal IPC handler - works like a Fastify route
 * Automatically injects: userId, lang from session
 *
 * @template TBody - Request body type (use void for no params)
 * @template TReturn - Response type (use void for no return)
 *
 * @example
 * // GET with no params
 * ipcMain.handle('db:books:getAll',
 *     createHandler<void, BookProps[]>(
 *         async (userId, body, lang) => {
 *             return await Book.getBooks(userId, lang);
 *         }
 *     )
 * );
 * // Frontend: invoke('db:books:getAll')
 *
 * @example
 * // GET with 1 param
 * ipcMain.handle('db:book:get',
 *     createHandler<string, BookProps>(
 *         async (userId, bookId, lang) => {
 *             return await Book.getBook(bookId, userId, lang);
 *         }
 *     )
 * );
 * // Frontend: invoke('db:book:get', bookId)
 *
 * @example
 * // POST with object body
 * ipcMain.handle('db:book:create',
 *     createHandler<CreateBookData, string>(
 *         async (userId, data, lang) => {
 *             return await Book.addBook(userId, data, lang);
 *         }
 *     )
 * );
 * // Frontend: invoke('db:book:create', { title: '...', ... })
 *
 * @example
 * // DELETE with void return
 * ipcMain.handle('db:book:delete',
 *     createHandler<string, void>(
 *         async (userId, bookId, lang) => {
 *             await Book.deleteBook(bookId, userId, lang);
 *         }
 *     )
 * );
 * // Frontend: invoke('db:book:delete', bookId)
 */
export function createHandler<TBody = void, TReturn = void>(
    handler: (userId: string, body: TBody, lang: 'fr' | 'en') => TReturn | Promise<TReturn>
): (event: IpcMainInvokeEvent, body?: TBody) => Promise<TReturn> {
    return async function(event: IpcMainInvokeEvent, body?: TBody): Promise<TReturn> {
        const userId = getUserIdFromSession();
        const lang = getLangFromSession();

        if (!userId) {
            throw new Error('User not authenticated');
        }

        try {
            return await handler(userId, body as TBody, lang);
        } catch (error: unknown) {
            if (error instanceof Error) {
                console.error(`[DB] ${error.message}`);
                throw error;
            }
            throw new Error('An unknown error occurred.');
        }
    };
}
