/**
 * SQLite Database Access Module
 * Provides cross-platform database operations for Antigravity state.
 *
 * Uses better-sqlite3 for:
 * - Windows compatibility (no CLI dependency)
 * - Native performance
 * - Synchronous API (simple error handling)
 *
 * Includes auto-rebuild capability for handling Node.js version updates
 * that cause native module incompatibility.
 */

import { createRequire } from 'module';
import { ANTIGRAVITY_DB_PATH } from '../constants.js';
import { isModuleVersionError, attemptAutoRebuild, clearRequireCache } from '../utils/native-module-helper.js';
import { logger } from '../utils/logger.js';
import { NativeModuleError } from '../errors.js';

const require = createRequire(import.meta.url);

// Lazy-loaded Database constructor
let Database = null;
let moduleLoadError = null;

/**
 * Load the better-sqlite3 module with auto-rebuild on version mismatch
 * Uses synchronous require to maintain API compatibility
 * @returns {Function} The Database constructor
 * @throws {Error} If module cannot be loaded even after rebuild
 */
function loadDatabaseModule() {
    // Return cached module if already loaded
    if (Database) return Database;

    // Re-throw cached error if previous load failed permanently
    if (moduleLoadError) throw moduleLoadError;

    try {
        Database = require('better-sqlite3');
        return Database;
    } catch (error) {
        if (isModuleVersionError(error)) {
            logger.warn('[Database] Native module version mismatch detected');

            if (attemptAutoRebuild(error)) {
                // Clear require cache and retry
                try {
                    const resolvedPath = require.resolve('better-sqlite3');
                    // Clear the module and all its dependencies from cache
                    clearRequireCache(resolvedPath, require.cache);

                    Database = require('better-sqlite3');
                    logger.success('[Database] Module reloaded successfully after rebuild');
                    return Database;
                } catch (retryError) {
                    // Rebuild succeeded but reload failed - user needs to restart
                    moduleLoadError = new NativeModuleError(
                        'Native module rebuild completed. Please restart the server to apply the fix.',
                        true,  // rebuildSucceeded
                        true   // restartRequired
                    );
                    logger.info('[Database] Rebuild succeeded - server restart required');
                    throw moduleLoadError;
                }
            } else {
                moduleLoadError = new NativeModuleError(
                    'Failed to auto-rebuild native module. Please run manually:\n' +
                    '  npm rebuild better-sqlite3\n' +
                    'Or if using npx, find the package location in the error and run:\n' +
                    '  cd /path/to/better-sqlite3 && npm rebuild',
                    false,  // rebuildSucceeded
                    false   // restartRequired
                );
                throw moduleLoadError;
            }
        }

        // Non-version-mismatch error, just throw it
        throw error;
    }
}

/**
 * Query Antigravity database for authentication status
 * @param {string} [dbPath] - Optional custom database path
 * @returns {Object} Parsed auth data with apiKey, email, name, etc.
 * @throws {Error} If database doesn't exist, query fails, or no auth status found
 */
export function getAuthStatus(dbPath = ANTIGRAVITY_DB_PATH) {
    const Db = loadDatabaseModule();
    let db;
    try {
        // Open database in read-only mode
        db = new Db(dbPath, {
            readonly: true,
            fileMustExist: true
        });

        // Prepare and execute query
        const stmt = db.prepare(
            "SELECT value FROM ItemTable WHERE key = 'antigravityAuthStatus'"
        );
        const row = stmt.get();

        if (!row || !row.value) {
            throw new Error('No auth status found in database');
        }

        // Parse JSON value
        const authData = JSON.parse(row.value);

        if (!authData.apiKey) {
            throw new Error('Auth data missing apiKey field');
        }

        return authData;
    } catch (error) {
        // Enhance error messages for common issues
        if (error.code === 'SQLITE_CANTOPEN') {
            throw new Error(
                `Database not found at ${dbPath}. ` +
                'Make sure Antigravity is installed and you are logged in.'
            );
        }
        // Re-throw with context if not already our error
        if (error.message.includes('No auth status') || error.message.includes('missing apiKey')) {
            throw error;
        }
        // Re-throw native module errors from loadDatabaseModule without wrapping
        if (error instanceof NativeModuleError) {
            throw error;
        }
        throw new Error(`Failed to read Antigravity database: ${error.message}`);
    } finally {
        // Always close database connection
        if (db) {
            db.close();
        }
    }
}

/**
 * Check if database exists and is accessible
 * @param {string} [dbPath] - Optional custom database path
 * @returns {boolean} True if database exists and can be opened
 */
export function isDatabaseAccessible(dbPath = ANTIGRAVITY_DB_PATH) {
    let db;
    try {
        const Db = loadDatabaseModule();
        db = new Db(dbPath, {
            readonly: true,
            fileMustExist: true
        });
        return true;
    } catch {
        return false;
    } finally {
        if (db) {
            db.close();
        }
    }
}

export default {
    getAuthStatus,
    isDatabaseAccessible
};
