import { readFileSync, existsSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { parseStreamJsonEvent, extractText, isTurnComplete, } from '../../../../modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js';
const DEFAULT_POLL_INTERVAL_MS = 750;
export class EmberAnswerTransportClaudeGateway {
    sessionGateway;
    options;
    constructor(sessionGateway, options) {
        this.sessionGateway = sessionGateway;
        this.options = options;
    }
    start(options, subscriber) {
        const run = new EmberAnswerRunner(this.sessionGateway, this.options.homeDir, this.options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS, options, subscriber);
        run.begin();
        return { status: 'started', run };
    }
}
const MAX_TAIL_ATTEMPTS = 240;
class EmberAnswerRunner {
    sessionGateway;
    homeDir;
    pollIntervalMs;
    options;
    subscriber;
    cancelled = false;
    timer = null;
    byteOffset = 0;
    pendingLine = '';
    transcriptPath = null;
    projectDir = null;
    shortSessionId = null;
    attempts = 0;
    stopped = false;
    constructor(sessionGateway, homeDir, pollIntervalMs, options, subscriber) {
        this.sessionGateway = sessionGateway;
        this.homeDir = homeDir;
        this.pollIntervalMs = pollIntervalMs;
        this.options = options;
        this.subscriber = subscriber;
    }
    begin() {
        void this.dispatchThenTail();
    }
    cancel() {
        this.cancelled = true;
        this.stopTimer();
        this.stopSession();
    }
    async dispatchThenTail() {
        const dispatch = await this.sessionGateway.dispatch({
            prompt: this.options.question,
            flags: {
                model: 'sonnet',
                permissionMode: 'auto',
                systemPrompt: this.options.systemPrompt,
                mcpConfigJson: '{"mcpServers":{}}',
                allowedTools: 'Read,Glob,Grep',
                disallowedTools: 'Edit,Write,Bash,Task',
            },
            localPath: this.options.projectPath,
            jobId: `ember-${Date.now()}`,
            jobType: 'ember-chat',
        });
        if (dispatch.status !== 'dispatched') {
            this.fail('ember-answer-dispatch-failed');
            return;
        }
        const slug = this.options.projectPath.replace(/\//g, '-');
        this.projectDir = join(this.homeDir, '.claude', 'projects', slug);
        this.shortSessionId = dispatch.sessionId;
        this.scheduleTail();
    }
    scheduleTail() {
        if (this.cancelled) {
            return;
        }
        this.timer = setTimeout(() => {
            this.tailOnce();
        }, this.pollIntervalMs);
    }
    tailOnce() {
        if (this.cancelled) {
            return;
        }
        this.attempts += 1;
        this.resolveTranscript();
        const completed = this.readNewLines();
        if (completed) {
            this.finish();
            return;
        }
        if (this.attempts >= MAX_TAIL_ATTEMPTS) {
            this.fail('ember-answer-timeout');
            return;
        }
        this.scheduleTail();
    }
    resolveTranscript() {
        if (this.transcriptPath !== null || this.projectDir === null || this.shortSessionId === null) {
            return;
        }
        if (!existsSync(this.projectDir)) {
            return;
        }
        const match = readdirSync(this.projectDir).find((name) => name.startsWith(this.shortSessionId ?? '') && name.endsWith('.jsonl'));
        if (match !== undefined) {
            this.transcriptPath = join(this.projectDir, match);
        }
    }
    readNewLines() {
        if (this.transcriptPath === null || !existsSync(this.transcriptPath)) {
            return false;
        }
        let raw;
        try {
            raw = readFileSync(this.transcriptPath, 'utf-8');
        }
        catch {
            this.fail('ember-answer-transcript-unreadable');
            return false;
        }
        const fresh = raw.slice(this.byteOffset);
        this.byteOffset = raw.length;
        this.pendingLine += fresh;
        const lines = this.pendingLine.split('\n');
        this.pendingLine = lines.pop() ?? '';
        let terminal = false;
        for (const line of lines) {
            if (line.trim().length === 0) {
                continue;
            }
            const event = parseStreamJsonEvent(line);
            if (event === null) {
                continue;
            }
            const text = extractText(event);
            if (text !== null) {
                this.subscriber.onChunk(text);
            }
            if (isTurnComplete(event)) {
                terminal = true;
            }
        }
        return terminal;
    }
    finish() {
        if (this.cancelled) {
            return;
        }
        this.readNewLines();
        this.stopTimer();
        this.stopSession();
        this.subscriber.onDone();
    }
    fail(message) {
        if (this.cancelled) {
            return;
        }
        this.cancel();
        this.subscriber.onError(message);
    }
    stopSession() {
        if (this.stopped || this.shortSessionId === null) {
            return;
        }
        this.stopped = true;
        void this.sessionGateway.stop(this.shortSessionId);
    }
    stopTimer() {
        if (this.timer !== null) {
            clearTimeout(this.timer);
            this.timer = null;
        }
    }
}
//# sourceMappingURL=emberAnswerTransport.claude.gateway.js.map