import { EventEmitter } from 'events';
import { BridgeClient } from './bridge-client.js';
import { ensureBridgeReady, restartBridge } from './bridge-manager.js';
import { NetworkError } from './errors.js';
import { getSocketPath, getLogsDir } from './utils.js';
import { createLogger } from './logger.js';
const logger = createLogger('session-client');
export class SessionClient extends EventEmitter {
    bridgeClient;
    sessionName;
    constructor(sessionName, bridgeClient) {
        super();
        this.sessionName = sessionName;
        this.bridgeClient = bridgeClient;
        this.setupNotificationForwarding();
    }
    setupNotificationForwarding() {
        this.bridgeClient.on('notification', (notification) => {
            logger.debug(`Forwarding notification: ${notification.method}`);
            this.emit('notification', notification);
        });
    }
    async withRetry(operation, operationName) {
        try {
            return await operation();
        }
        catch (error) {
            if (!(error instanceof NetworkError)) {
                const err = error;
                const logPath = `${getLogsDir()}/bridge-${this.sessionName}.log`;
                err.message = `${err.message}. For details, check logs at ${logPath}`;
                throw error;
            }
            logger.debug(`Socket error during ${operationName}, will restart bridge...`);
            await this.bridgeClient.close();
            await restartBridge(this.sessionName);
            const socketPath = getSocketPath(this.sessionName);
            this.bridgeClient = new BridgeClient(socketPath);
            this.setupNotificationForwarding();
            await this.bridgeClient.connect();
            logger.debug(`Reconnected to bridge for ${this.sessionName}, retrying ${operationName}`);
            return await operation();
        }
    }
    async close() {
        await this.bridgeClient.close();
    }
    async getServerDetails() {
        return this.withRetry(() => this.bridgeClient.request('getServerDetails'), 'getServerDetails');
    }
    async ping() {
        return this.withRetry(() => this.bridgeClient.request('ping').then(() => undefined), 'ping');
    }
    async listTools(cursor) {
        return this.withRetry(() => this.bridgeClient.request('listTools', cursor), 'listTools');
    }
    async callTool(name, args) {
        return this.withRetry(() => this.bridgeClient.request('callTool', { name, arguments: args }), 'callTool');
    }
    async listResources(cursor) {
        return this.withRetry(() => this.bridgeClient.request('listResources', cursor), 'listResources');
    }
    async listResourceTemplates(cursor) {
        return this.withRetry(() => this.bridgeClient.request('listResourceTemplates', cursor), 'listResourceTemplates');
    }
    async readResource(uri) {
        return this.withRetry(() => this.bridgeClient.request('readResource', { uri }), 'readResource');
    }
    async subscribeResource(uri) {
        return this.withRetry(() => this.bridgeClient.request('subscribeResource', { uri }).then(() => undefined), 'subscribeResource');
    }
    async unsubscribeResource(uri) {
        return this.withRetry(() => this.bridgeClient.request('unsubscribeResource', { uri }).then(() => undefined), 'unsubscribeResource');
    }
    async listPrompts(cursor) {
        return this.withRetry(() => this.bridgeClient.request('listPrompts', cursor), 'listPrompts');
    }
    async getPrompt(name, args) {
        return this.withRetry(() => this.bridgeClient.request('getPrompt', { name, arguments: args }), 'getPrompt');
    }
    async setLoggingLevel(level) {
        return this.withRetry(() => this.bridgeClient.request('setLoggingLevel', level).then(() => undefined), 'setLoggingLevel');
    }
    getSDKClient() {
        throw new Error('SessionClient does not expose underlying SDK client');
    }
}
export async function createSessionClient(sessionName) {
    const socketPath = await ensureBridgeReady(sessionName);
    const bridgeClient = new BridgeClient(socketPath);
    await bridgeClient.connect();
    logger.debug(`Created SessionClient for ${sessionName}`);
    return new SessionClient(sessionName, bridgeClient);
}
export async function withSessionClient(sessionName, callback) {
    const client = await createSessionClient(sessionName);
    try {
        return await callback(client);
    }
    finally {
        await client.close();
    }
}
//# sourceMappingURL=session-client.js.map