/**
 * Database Error Handler for Frontend
 * Handles errors from Electron IPC calls
 */

export interface SerializedError {
    name: string;
    message: string;
    messageFr: string;
    messageEn: string;
    statusCode: number;
    stack?: string;
}

/**
 * Check if error is a serialized database error
 */
export function isDbError(error: unknown): error is SerializedError {
    return (
        typeof error === 'object' &&
        error !== null &&
        'name' in error &&
        'messageFr' in error &&
        'messageEn' in error &&
        'statusCode' in error
    );
}

/**
 * Get error message based on current language
 */
export function getErrorMessage(error: SerializedError, lang: 'fr' | 'en' = 'fr'): string {
    return lang === 'fr' ? error.messageFr : error.messageEn;
}

/**
 * Handle database operation with error catching
 * Use this to wrap all IPC calls
 */
export async function handleDbOperation<T>(
    operation: () => Promise<T>,
    onError?: (error: SerializedError) => void,
    lang: 'fr' | 'en' = 'fr'
): Promise<T> {
    try {
        return await operation();
    } catch (error: unknown) {
        if (isDbError(error)) {
            const errorMessage = getErrorMessage(error, lang);
            console.error(`[DB Error ${error.statusCode}]: ${errorMessage}`);

            if (onError) {
                onError(error);
            } else {
                // Default: throw with localized message
                throw new Error(errorMessage);
            }
        }

        // Not a database error, rethrow as-is
        throw error;
    }
}

/**
 * React Hook for database operations
 * Example usage in a React component:
 *
 * const { data, error, loading, execute } = useDbOperation();
 *
 * const loadBooks = async () => {
 *   await execute(() => window.electron.invoke('db:book:getAll'));
 * };
 */
export function useDbOperation<T>() {
    const [data, setData] = React.useState<T | null>(null);
    const [error, setError] = React.useState<SerializedError | null>(null);
    const [loading, setLoading] = React.useState<boolean>(false);

    const execute = async (
        operation: () => Promise<T>,
        lang: 'fr' | 'en' = 'fr'
    ): Promise<T | null> => {
        setLoading(true);
        setError(null);

        try {
            const result = await handleDbOperation(
                operation,
                (err) => setError(err),
                lang
            );
            setData(result);
            setLoading(false);
            return result;
        } catch (err) {
            setLoading(false);
            return null;
        }
    };

    return { data, error, loading, execute };
}

// For non-React usage
import React from 'react';
