/**
 * SQLite Initialization and Management for TimeSafari Electron
 * 
 * This module handles the complete lifecycle of SQLite database initialization,
 * connection management, and IPC communication in the TimeSafari Electron app.
 * 
 * Key Features:
 * - Database path management with proper permissions
 * - Plugin initialization and state verification
 * - Connection lifecycle management
 * - PRAGMA configuration for optimal performance
 * - Migration system integration with configurable logging
 * - Error handling and recovery
 * - IPC communication layer with proper cleanup
 * 
 * Database Configuration:
 * - Uses WAL journal mode for better concurrency
 * - Configures optimal PRAGMA settings
 * - Implements connection pooling
 * - Handles encryption (when enabled)
 * 
 * State Management:
 * - Tracks plugin initialization state
 * - Monitors connection health
 * - Manages transaction state
 * - Implements recovery mechanisms
 * 
 * Error Handling:
 * - Custom SQLiteError class for detailed error tracking
 * - Comprehensive error logging
 * - Automatic recovery attempts
 * - State verification before operations
 * 
 * Security:
 * - Proper file permissions (0o755)
 * - Write access verification
 * - Connection state validation
 * - Transaction safety
 * 
 * Performance:
 * - WAL mode for better concurrency
 * - Optimized PRAGMA settings
 * - Connection pooling
 * - Efficient state management
 * 
 * @author Matthew Raymer <matthew.raymer@anomalistdesign.com>
 * @version 1.0.0
 * @since 2025-06-01
 */

import { app, ipcMain } from 'electron';
import { CapacitorSQLite } from '@capacitor-community/sqlite/electron/dist/plugin.js';
import * as SQLiteModule from '@capacitor-community/sqlite/electron/dist/plugin.js';
import fs from 'fs';
import path from 'path';
import os from 'os';
import { runMigrations } from './sqlite-migrations';
import { logger } from './logger';
import { startDatabaseOperation, endDatabaseOperation } from '../setup';

// Types for state management
interface PluginState {
  isInitialized: boolean;
  isAvailable: boolean;
  lastVerified: Date | null;
  lastError: Error | null;
  instance: any | null;
}

interface TransactionState {
  isActive: boolean;
  lastVerified: Date | null;
  database: string | null;
}

// State tracking
let pluginState: PluginState = {
  isInitialized: false,
  isAvailable: false,
  lastVerified: null,
  lastError: null,
  instance: null
};

let transactionState: TransactionState = {
  isActive: false,
  lastVerified: null,
  database: null
};

// Constants
const MAX_RECOVERY_ATTEMPTS = 3;
const RECOVERY_DELAY_MS = 1000;
const VERIFICATION_TIMEOUT_MS = 5000;

// Type definitions for SQLite operations
interface SQLiteConnectionOptions {
  database: string;
  version?: number;
  readOnly?: boolean;
  readonly?: boolean;
  mode?: string;
  useNative?: boolean;
  [key: string]: unknown;
}

interface SQLiteQueryOptions {
  statement: string;
  values?: unknown[];
}

interface SQLiteExecuteOptions {
  statements: SQLiteQueryOptions[];
  transaction?: boolean;
}

interface SQLiteResult {
  changes?: { changes: number; lastId?: number };
  values?: Record<string, unknown>[];
}

interface SQLiteEchoResult {
  value: string;
}

// Enhanced error types
class SQLiteError extends Error {
  constructor(
    message: string,
    public context: string,
    public code: string = 'SQLITE_ERROR',
    public originalError?: unknown,
    public details?: Record<string, unknown>
  ) {
    super(message);
    this.name = 'SQLiteError';
  }

  toJSON() {
    return {
      name: this.name,
      message: this.message,
      context: this.context,
      code: this.code,
      details: this.details,
      stack: this.stack,
      originalError: this.originalError instanceof Error ? {
        name: this.originalError.name,
        message: this.originalError.message,
        stack: this.originalError.stack
      } : this.originalError
    };
  }
}

// Validation utilities
const validateConnectionOptions = (options: unknown): SQLiteConnectionOptions => {
  if (!options || typeof options !== 'object') {
    throw new SQLiteError('Invalid connection options', 'validation', 'SQLITE_INVALID_OPTIONS');
  }

  const opts = options as SQLiteConnectionOptions;
  if (!opts.database || typeof opts.database !== 'string') {
    throw new SQLiteError('Database name is required', 'validation', 'SQLITE_INVALID_DATABASE');
  }

  return opts;
};

const validateQueryOptions = (options: unknown): SQLiteQueryOptions => {
  if (!options || typeof options !== 'object') {
    throw new SQLiteError('Invalid query options', 'validation', 'SQLITE_INVALID_OPTIONS');
  }

  const opts = options as SQLiteQueryOptions;
  if (!opts.statement || typeof opts.statement !== 'string') {
    throw new SQLiteError('SQL statement is required', 'validation', 'SQLITE_INVALID_STATEMENT');
  }

  if (opts.values && !Array.isArray(opts.values)) {
    throw new SQLiteError('Values must be an array', 'validation', 'SQLITE_INVALID_VALUES');
  }

  return opts;
};

// Enhanced error handler with more context
const handleError = (error: unknown, context: string, details?: Record<string, unknown>): SQLiteError => {
  const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
  const errorStack = error instanceof Error ? error.stack : undefined;
  
  // Determine error code based on context and message
  let code = 'SQLITE_ERROR';
  if (errorMessage.includes('database is locked')) {
    code = 'SQLITE_BUSY';
  } else if (errorMessage.includes('no such table')) {
    code = 'SQLITE_NO_TABLE';
  } else if (errorMessage.includes('syntax error')) {
    code = 'SQLITE_SYNTAX_ERROR';
  }
  
  logger.error(`Error in ${context}:`, {
    message: errorMessage,
    stack: errorStack,
    context,
    code,
    details,
    timestamp: new Date().toISOString()
  });
  
  return new SQLiteError(
    `${context} failed: ${errorMessage}`,
    context,
    code,
    error,
    details
  );
};

// Add delay utility with timeout
const delay = (ms: number, timeoutMs: number = VERIFICATION_TIMEOUT_MS): Promise<void> => {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(new SQLiteError('Operation timed out', 'delay'));
    }, timeoutMs);
    
    setTimeout(() => {
      clearTimeout(timeout);
      resolve();
    }, ms);
  });
};

// Plugin state verification
const verifyPluginState = async (): Promise<boolean> => {
  if (!pluginState.instance || !pluginState.isInitialized) {
    return false;
  }
  
  try {
    // Test plugin responsiveness
    const echoResult = await pluginState.instance.echo({ value: 'test' });
    if (!echoResult || echoResult.value !== 'test') {
      throw new SQLiteError('Plugin echo test failed', 'verifyPluginState');
    }
    
    pluginState.isAvailable = true;
    pluginState.lastVerified = new Date();
    pluginState.lastError = null;
    
    return true;
  } catch (error) {
    pluginState.isAvailable = false;
    pluginState.lastError = handleError(error, 'verifyPluginState');
    return false;
  }
};

// Transaction state verification
const verifyTransactionState = async (database: string): Promise<boolean> => {
  if (!pluginState.instance || !pluginState.isAvailable) {
    return false;
  }
  
  try {
    // Check if we're in a transaction
    const isActive = await pluginState.instance.isTransactionActive({ database });
    
    // Only update state if it's different
    if (isActive !== transactionState.isActive || transactionState.database !== database) {
    transactionState.isActive = isActive;
    transactionState.lastVerified = new Date();
      transactionState.database = isActive ? database : null;
    }
    
    return true;
  } catch (error) {
    // Reset state on error
    transactionState.isActive = false;
    transactionState.lastVerified = new Date();
    transactionState.database = null;
    
    logger.error('Transaction state verification failed:', error);
    return false;
  }
};

// Plugin initialization
const initializePlugin = async (): Promise<boolean> => {
  logger.info('Starting plugin initialization');
  
  try {
    // Create plugin instance
    let rawPlugin;
    if (SQLiteModule.default?.CapacitorSQLite) {
      logger.debug('Using default export CapacitorSQLite');
      rawPlugin = new SQLiteModule.default.CapacitorSQLite();
    } else {
      logger.debug('Using direct CapacitorSQLite class');
      rawPlugin = new CapacitorSQLite();
    }
    
    // Verify instance
    if (!rawPlugin || typeof rawPlugin !== 'object') {
      throw new SQLiteError('Invalid plugin instance created', 'initializePlugin');
    }
    
    // Test plugin functionality
    const echoResult = await rawPlugin.echo({ value: 'test' });
    if (!echoResult || echoResult.value !== 'test') {
      throw new SQLiteError('Plugin echo test failed', 'initializePlugin');
    }
    
    // Update state only after successful verification
    pluginState = {
      isInitialized: true,
      isAvailable: true,
      lastVerified: new Date(),
      lastError: null,
      instance: rawPlugin
    };
    
    logger.info('Plugin initialized successfully');
    return true;
  } catch (error) {
    pluginState = {
      isInitialized: false,
      isAvailable: false,
      lastVerified: new Date(),
      lastError: handleError(error, 'initializePlugin'),
      instance: null
    };
    
    logger.error('Plugin initialization failed:', {
      error: pluginState.lastError,
      timestamp: new Date().toISOString()
    });
    
    return false;
  }
};

// Recovery mechanism
const recoverPluginState = async (attempt: number = 1): Promise<boolean> => {
  logger.info(`Attempting plugin state recovery (attempt ${attempt}/${MAX_RECOVERY_ATTEMPTS})`);
  
  if (attempt > MAX_RECOVERY_ATTEMPTS) {
    logger.error('Max recovery attempts reached');
    return false;
  }
  
  try {
    // Cleanup existing connection if any
    if (pluginState.instance) {
      try {
        await pluginState.instance.closeConnection({ database: 'timesafari' });
        logger.debug('Closed existing database connection during recovery');
      } catch (error) {
        logger.warn('Error closing connection during recovery:', error);
      }
    }
    
    // Reset state
    pluginState = {
      isInitialized: false,
      isAvailable: false,
      lastVerified: new Date(),
      lastError: null,
      instance: null
    };
    
    // Wait before retry with exponential backoff
    const backoffDelay = RECOVERY_DELAY_MS * Math.pow(2, attempt - 1);
    await delay(backoffDelay);
    
    // Reinitialize
    const success = await initializePlugin();
    if (!success && attempt < MAX_RECOVERY_ATTEMPTS) {
      return recoverPluginState(attempt + 1);
    }
    
    return success;
  } catch (error) {
    logger.error('Plugin recovery failed:', error);
    if (attempt < MAX_RECOVERY_ATTEMPTS) {
      return recoverPluginState(attempt + 1);
    }
    return false;
  }
};

/**
 * Initializes database paths and ensures proper permissions
 * 
 * This function:
 * 1. Creates the database directory if it doesn't exist
 * 2. Sets proper permissions (0o755)
 * 3. Verifies write access
 * 4. Returns the absolute path to the database directory
 * 
 * @returns {Promise<string>} Absolute path to database directory
 * @throws {SQLiteError} If directory creation or permission setting fails
 */
const initializeDatabasePaths = async (): Promise<string> => {
  try {
    // Get the absolute app data directory
    const appDataDir = path.join(os.homedir(), 'Databases', 'TimeSafari');
    logger.info('App data directory:', appDataDir);
    
    // Ensure directory exists with proper permissions
    if (!fs.existsSync(appDataDir)) {
      await fs.promises.mkdir(appDataDir, { 
        recursive: true,
        mode: 0o755
      });
    } else {
      await fs.promises.chmod(appDataDir, 0o755);
    }
    
    // Verify directory permissions
    const stats = await fs.promises.stat(appDataDir);
    logger.info('Directory permissions:', {
      mode: stats.mode.toString(8),
      uid: stats.uid,
      gid: stats.gid,
      isDirectory: stats.isDirectory(),
      isWritable: !!(stats.mode & 0o200)
    });
    
    // Test write access
    const testFile = path.join(appDataDir, '.write-test');
    await fs.promises.writeFile(testFile, 'test');
    await fs.promises.unlink(testFile);
    
    return appDataDir;
  } catch (error) {
    throw handleError(error, 'initializeDatabasePaths');
  }
};

/**
 * Main SQLite initialization function
 * 
 * Orchestrates the complete database initialization process:
 * 1. Sets up database paths
 * 2. Initializes the SQLite plugin
 * 3. Creates and verifies database connection
 * 4. Configures database PRAGMAs
 * 5. Runs database migrations
 * 6. Handles errors and recovery
 * 
 * Database Configuration:
 * - Uses WAL journal mode
 * - Enables foreign keys
 * - Sets optimal page size and cache
 * - Configures busy timeout
 * 
 * Error Recovery:
 * - Implements exponential backoff
 * - Verifies plugin state
 * - Attempts connection recovery
 * - Maintains detailed error logs
 * 
 * @throws {SQLiteError} If initialization fails and recovery is unsuccessful
 */
export async function initializeSQLite(): Promise<void> {
  logger.info('Starting SQLite initialization');
  
  try {
    // Initialize database paths
    const dbDir = await initializeDatabasePaths();
    const dbPath = path.join(dbDir, 'timesafariSQLite.db');
    
    // Initialize plugin
    if (!await initializePlugin()) {
      throw new SQLiteError('Plugin initialization failed', 'initializeSQLite');
    }
    
    // Verify plugin state
    if (!await verifyPluginState()) {
      throw new SQLiteError('Plugin state verification failed', 'initializeSQLite');
    }
    
    // Set up database connection - simplified to match sacred-sql
    const connectionOptions = {
      database: 'timesafari',
      version: 1,
      readOnly: false,
      useNative: true,
      mode: 'rwc'
    };
    
    // Create and verify connection
    logger.debug('Creating database connection:', connectionOptions);
    await pluginState.instance.createConnection(connectionOptions);
    await delay(500); // Wait for connection registration
    
    const isRegistered = await pluginState.instance.isDatabase({
      database: connectionOptions.database
    });
    
    if (!isRegistered) {
      throw new SQLiteError('Database not registered', 'initializeSQLite');
    }
    
    // Open database
    logger.debug('Opening database with options:', connectionOptions);
    await pluginState.instance.open({
      ...connectionOptions,
      mode: 'rwc'
    });
    
    // Set PRAGMAs to match sacred-sql approach
    const pragmaStatements = [
      'PRAGMA journal_mode = MEMORY;', // Changed to MEMORY mode to match sacred-sql
      'PRAGMA foreign_keys = ON;',
      'PRAGMA synchronous = NORMAL;',
      'PRAGMA temp_store = MEMORY;',
      'PRAGMA page_size = 4096;',
      'PRAGMA cache_size = 2000;'
      // Removed WAL-specific settings
    ];
    
    logger.debug('Setting database PRAGMAs');
    for (const statement of pragmaStatements) {
      try {
        logger.debug('Executing PRAGMA:', statement);
        const result = await pluginState.instance.execute({
        database: connectionOptions.database,
          statements: statement,
          transaction: false
        });
        logger.debug('PRAGMA result:', { statement, result });
      } catch (error) {
        logger.error('PRAGMA execution failed:', {
          statement,
          error: error instanceof Error ? {
            message: error.message,
            stack: error.stack,
            name: error.name
          } : error
        });
        throw error;
      }
    }
    
    // Run migrations with enhanced error logging
    logger.info('Starting database migrations');
    const migrationResults = await runMigrations(
      pluginState.instance,
      connectionOptions.database
    );
    
    // Check migration results with detailed logging
    const failedMigrations = migrationResults.filter(r => !r.success);
    if (failedMigrations.length > 0) {
      logger.error('Migration failures:', {
        totalMigrations: migrationResults.length,
        failedCount: failedMigrations.length,
        failures: failedMigrations.map(f => ({
          version: f.version,
          name: f.name,
          error: f.error instanceof Error ? {
            message: f.error.message,
            stack: f.error.stack,
            name: f.error.name
          } : f.error,
          state: f.state
        }))
      });
      throw new SQLiteError(
        `Database migrations failed: ${failedMigrations.map(f => f.name).join(', ')}`,
        'initializeSQLite',
        'SQLITE_MIGRATION_FAILED',
        failedMigrations
      );
    }
    
    logger.info('SQLite initialization completed successfully');
  } catch (error) {
    const sqliteError = handleError(error, 'initializeSQLite');
    logger.error('SQLite initialization failed:', {
      error: sqliteError,
      pluginState: {
        isInitialized: pluginState.isInitialized,
        isAvailable: pluginState.isAvailable,
        lastVerified: pluginState.lastVerified,
        lastError: pluginState.lastError
      }
    });
    
    // Attempt recovery
    if (await recoverPluginState()) {
      logger.info('Recovery successful, retrying initialization');
      return initializeSQLite();
    }
    
    throw sqliteError;
  }
}

// Add IPC handler tracking
const registeredHandlers = new Set<string>();

/**
 * Removes all registered SQLite IPC handlers
 * Called before re-registering handlers to prevent duplicates
 */
const cleanupSQLiteHandlers = (): void => {
  logger.debug('Cleaning up SQLite IPC handlers');
  for (const channel of registeredHandlers) {
    try {
      ipcMain.removeHandler(channel);
      logger.debug(`Removed handler for channel: ${channel}`);
    } catch (error) {
      logger.warn(`Failed to remove handler for channel ${channel}:`, error);
    }
  }
  registeredHandlers.clear();
};

/**
 * Registers an IPC handler with tracking
 * @param channel The IPC channel to register
 * @param handler The handler function
 */
const registerHandler = (channel: string, handler: (...args: any[]) => Promise<any>): void => {
  if (registeredHandlers.has(channel)) {
    logger.debug(`Handler already registered for channel: ${channel}, removing first`);
    ipcMain.removeHandler(channel);
  }
  ipcMain.handle(channel, handler);
  registeredHandlers.add(channel);
  logger.debug(`Registered handler for channel: ${channel}`);
};

/**
 * Sets up IPC handlers for SQLite operations
 * Registers handlers for all SQLite operations defined in VALID_CHANNELS.invoke
 * Tracks database operations to prevent reloads during critical operations
 * Implements proper handler cleanup to prevent duplicates
 * 
 * @author Matthew Raymer
 */
export function setupSQLiteHandlers(): void {
  logger.info('Setting up SQLite IPC handlers');
  
  // Clean up any existing handlers first
  cleanupSQLiteHandlers();

  // Handler for checking SQLite availability
  registerHandler('sqlite-is-available', async () => {
    logger.debug('Checking SQLite availability');
    try {
      startDatabaseOperation();
      const isAvailable = await verifyPluginState();
      logger.debug('SQLite availability check:', { isAvailable });
      return isAvailable;
    } catch (error) {
      logger.error('SQLite availability check failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for echo test
  registerHandler('sqlite-echo', async (_event, { value }) => {
    logger.debug('SQLite echo test:', { value });
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-echo');
      }
      const result = await pluginState.instance.echo({ value });
      logger.debug('SQLite echo result:', result);
      return result;
    } catch (error) {
      logger.error('SQLite echo failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });
  
  // Handler for creating database connection
  registerHandler('sqlite-create-connection', async (_event, options: SQLiteConnectionOptions) => {
    logger.debug('Creating SQLite connection:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-create-connection');
      }
      const validatedOptions = validateConnectionOptions(options);
      await pluginState.instance.createConnection(validatedOptions);
      logger.debug('SQLite connection created successfully');
      return true;
    } catch (error) {
      logger.error('SQLite connection creation failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });
  
  // Handler for executing SQL statements
  registerHandler('sqlite-execute', async (_event, options: SQLiteExecuteOptions) => {
    logger.debug('Executing SQL statements:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-execute');
      }
      const result = await pluginState.instance.execute(options);
      logger.debug('SQL execution result:', result);
      return result;
    } catch (error) {
      logger.error('SQL execution failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });
  
  // Handler for querying data
  registerHandler('sqlite-query', async (_event, options: SQLiteQueryOptions) => {
    logger.debug('Querying SQLite:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-query');
      }
      const result = await pluginState.instance.query(options);
      logger.debug('SQL query result:', result);
      return result;
    } catch (error) {
      logger.error('SQL query failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for running SQL statements
  registerHandler('sqlite-run', async (_event, options: SQLiteQueryOptions) => {
    logger.debug('Running SQL statement:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-run');
      }
      const result = await pluginState.instance.run(options);
      logger.debug('SQL run result:', result);
      return result;
    } catch (error) {
      logger.error('SQL run failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for closing database connection
  registerHandler('sqlite-close-connection', async (_event, options: { database: string }) => {
    logger.debug('Closing SQLite connection:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-close-connection');
      }
      await pluginState.instance.closeConnection(options);
      logger.debug('SQLite connection closed successfully');
      return true;
    } catch (error) {
      logger.error('SQLite connection close failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for opening database
  registerHandler('sqlite-open', async (_event, options: SQLiteConnectionOptions) => {
    logger.debug('Opening SQLite database:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-open');
      }
      await pluginState.instance.open(options);
      logger.debug('SQLite database opened successfully');
      return true;
    } catch (error) {
      logger.error('SQLite database open failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for closing database
  registerHandler('sqlite-close', async (_event, options: { database: string }) => {
    logger.debug('Closing SQLite database:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-close');
      }
      await pluginState.instance.close(options);
      logger.debug('SQLite database closed successfully');
      return true;
    } catch (error) {
      logger.error('SQLite database close failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for checking if database is open
  registerHandler('sqlite-is-db-open', async (_event, options: { database: string }) => {
    logger.debug('Checking if SQLite database is open:', options);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-is-db-open');
      }
      const isOpen = await pluginState.instance.isDBOpen(options);
      logger.debug('SQLite database open check:', { isOpen });
      return isOpen;
    } catch (error) {
      logger.error('SQLite database open check failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for getting database path
  registerHandler('get-path', async () => {
    logger.debug('Getting database path');
    try {
      startDatabaseOperation();
      const dbDir = await initializeDatabasePaths();
      const dbPath = path.join(dbDir, 'timesafariSQLite.db');
      logger.debug('Database path:', dbPath);
      return dbPath;
    } catch (error) {
      logger.error('Failed to get database path:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });
  
  // Handler for getting base path
  registerHandler('get-base-path', async () => {
    logger.debug('Getting base path');
    try {
      startDatabaseOperation();
      const dbDir = await initializeDatabasePaths();
      logger.debug('Base path:', dbDir);
      return dbDir;
    } catch (error) {
      logger.error('Failed to get base path:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  // Handler for SQLite status updates
  registerHandler('sqlite-status', async (_event, status: { status: string; database: string; timestamp: number }) => {
    logger.debug('SQLite status update:', status);
    try {
      startDatabaseOperation();
      if (!pluginState.instance) {
        throw new SQLiteError('Plugin not initialized', 'sqlite-status');
      }
      
      // Verify database is still open
      const isOpen = await pluginState.instance.isDBOpen({ database: status.database });
      if (!isOpen) {
        throw new SQLiteError('Database not open', 'sqlite-status');
      }
      
      logger.info('SQLite status update processed:', { 
        status: status.status,
        database: status.database,
        timestamp: new Date(status.timestamp).toISOString()
      });
      
      return { success: true, isOpen };
    } catch (error) {
      logger.error('SQLite status update failed:', error);
      throw error;
    } finally {
      endDatabaseOperation();
    }
  });

  logger.info('SQLite IPC handlers setup complete');
} 

// Update transaction management to be more careful
const beginTransaction = async (database: string): Promise<void> => {
  if (!pluginState.instance || !pluginState.isAvailable) {
    throw new SQLiteError('Database not available', 'beginTransaction');
  }

  // Verify current state first
  await verifyTransactionState(database);
  if (transactionState.isActive) {
    throw new SQLiteError('Transaction already active', 'beginTransaction');
  }

  try {
    await pluginState.instance.beginTransaction({ database });
    transactionState.isActive = true;
    transactionState.lastVerified = new Date();
    transactionState.database = database;
  } catch (error) {
    transactionState.isActive = false;
    transactionState.lastVerified = new Date();
    transactionState.database = null;
    throw new SQLiteError('Failed to begin transaction', 'beginTransaction', error);
  }
};

const commitTransaction = async (database: string): Promise<void> => {
  if (!pluginState.instance || !pluginState.isAvailable) {
    throw new SQLiteError('Database not available', 'commitTransaction');
  }

  // Verify current state first
  await verifyTransactionState(database);
  if (!transactionState.isActive || transactionState.database !== database) {
    throw new SQLiteError('No active transaction', 'commitTransaction');
  }

  try {
    await pluginState.instance.commitTransaction({ database });
    transactionState.isActive = false;
    transactionState.lastVerified = new Date();
    transactionState.database = null;
  } catch (error) {
    // Don't reset state on error - let rollback handle it
    throw new SQLiteError('Failed to commit transaction', 'commitTransaction', error);
  }
};

const rollbackTransaction = async (database: string): Promise<void> => {
  if (!pluginState.instance || !pluginState.isAvailable) {
    return; // Just return if plugin not available
  }

  // Only attempt rollback if we think we're in a transaction
  if (transactionState.isActive && transactionState.database === database) {
    try {
      await pluginState.instance.rollbackTransaction({ database });
    } catch (error) {
      logger.error('Rollback failed:', error);
    }
  }

  // Always reset state after rollback attempt
  transactionState.isActive = false;
  transactionState.lastVerified = new Date();
  transactionState.database = null;
};