import { SQL as BunSQL } from 'bun';
import { mergeReconnectConfig, DEFAULT_RECONNECT_CONFIG } from "./reconnect.js";
import { injectSslMode } from "./tls.js";
/**
 * Whether Bun.SQL has already been patched.
 */
let _patched = false;
/**
 * Global reconnect configuration for patched Bun.SQL instances.
 */
let _globalReconnectConfig = { ...DEFAULT_RECONNECT_CONFIG };
/**
 * Callbacks for reconnection events.
 */
let _onReconnect;
let _onReconnected;
let _onReconnectFailed;
/**
 * Patched Bun SQL class that normalizes TLS configuration.
 *
 * This is a Proxy around Bun's native `SQL` class that intercepts
 * construction to ensure `sslmode=require` is present in the URL
 * when `tls` config is provided. This works around a Bun issue where
 * the `tls` option alone doesn't trigger PostgreSQL TLS negotiation.
 *
 * All other behavior is identical to `Bun.SQL`.
 *
 * @example
 * ```typescript
 * import { SQL } from '@agentuity/postgres';
 *
 * // This now works correctly — sslmode=require is injected automatically
 * const sql = new SQL({
 *   url: 'postgresql://user:pass@host/db',
 *   tls: true,
 * });
 * ```
 */
const SQL = new Proxy(BunSQL, {
    construct(target, args, newTarget) {
        if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
            const opts = args[0];
            const url = opts.url;
            if (typeof url === 'string') {
                const injected = injectSslMode(url, opts.tls);
                if (injected !== url) {
                    args = [{ ...opts, url: injected }];
                }
            }
        }
        return Reflect.construct(target, args, newTarget);
    },
    get(target, prop, receiver) {
        // Ensure Symbol.hasInstance resolves to BunSQL's check so
        // `new SQL(...) instanceof SQL` works correctly.
        if (prop === Symbol.hasInstance) {
            return (instance) => instance instanceof BunSQL;
        }
        return Reflect.get(target, prop, receiver);
    },
});
/**
 * Patches Bun's native SQL class to add automatic reconnection support.
 *
 * This modifies the global `Bun.SQL` prototype to intercept connection close
 * events and automatically attempt reconnection with exponential backoff.
 *
 * **Note:** This is a global modification that affects all SQL instances created
 * after calling this function. Use with caution in shared environments.
 *
 * @param config - Optional configuration for reconnection behavior
 *
 * @example
 * ```typescript
 * import { patchBunSQL, SQL } from '@agentuity/postgres';
 *
 * // Patch with default settings
 * patchBunSQL();
 *
 * // Or with custom configuration
 * patchBunSQL({
 *   reconnect: {
 *     maxAttempts: 5,
 *     initialDelayMs: 200,
 *   },
 *   onreconnect: (attempt) => console.log(`Reconnecting... attempt ${attempt}`),
 *   onreconnected: () => console.log('Reconnected!'),
 * });
 *
 * // Now use Bun.SQL normally - it will auto-reconnect
 * const sql = new SQL({ url: process.env.DATABASE_URL });
 * const users = await sql`SELECT * FROM users`;
 * ```
 */
export function patchBunSQL(config) {
    if (_patched) {
        // Already patched, just update config if provided
        if (config?.reconnect) {
            _globalReconnectConfig = mergeReconnectConfig(config.reconnect);
        }
        if (config?.onreconnect)
            _onReconnect = config.onreconnect;
        if (config?.onreconnected)
            _onReconnected = config.onreconnected;
        if (config?.onreconnectfailed)
            _onReconnectFailed = config.onreconnectfailed;
        return;
    }
    // Store configuration
    if (config?.reconnect) {
        _globalReconnectConfig = mergeReconnectConfig(config.reconnect);
    }
    _onReconnect = config?.onreconnect;
    _onReconnected = config?.onreconnected;
    _onReconnectFailed = config?.onreconnectfailed;
    _patched = true;
}
/**
 * Returns whether Bun.SQL has been patched.
 */
export function isPatched() {
    return _patched;
}
/**
 * Resets the patch state (mainly for testing).
 * @internal
 */
export function _resetPatch() {
    _patched = false;
    _globalReconnectConfig = { ...DEFAULT_RECONNECT_CONFIG };
    _onReconnect = undefined;
    _onReconnected = undefined;
    _onReconnectFailed = undefined;
}
export { SQL };
//# sourceMappingURL=patch.js.map