import fsSync from 'node:fs';
import path from 'node:path';
import Database from 'better-sqlite3';
import { sessionsDb } from '../../../../modules/database/index.js';
import { getOpenCodeDatabasePath, normalizeProviderTimestamp, normalizeSessionName, readJsonRecord, readOptionalString, } from '../../../../shared/utils.js';
/**
 * Session indexer for OpenCode's SQLite-backed session store.
 */
export class OpenCodeSessionSynchronizer {
    provider = 'opencode';
    /**
     * Scans OpenCode's shared opencode.db and upserts active sessions into DB.
     */
    async synchronize(since) {
        const result = this.synchronizeRows(since);
        return result.processed;
    }
    /**
     * Handles watcher changes for opencode.db.
     */
    async synchronizeFile(filePath) {
        if (path.basename(filePath) !== 'opencode.db') {
            return null;
        }
        const result = this.synchronizeRows(undefined, 1);
        return result.firstSessionId;
    }
    synchronizeRows(since, limit) {
        const dbPath = getOpenCodeDatabasePath();
        if (!fsSync.existsSync(dbPath)) {
            return { processed: 0, firstSessionId: null };
        }
        const db = new Database(dbPath, { readonly: true, fileMustExist: true });
        try {
            const sinceMillis = since?.getTime() ?? null;
            const limitClause = limit ? 'LIMIT ?' : '';
            const params = limit ? [sinceMillis, sinceMillis, limit] : [sinceMillis, sinceMillis];
            const rows = db.prepare(`
        SELECT
          s.id AS id,
          s.directory AS directory,
          s.title AS title,
          s.time_created AS time_created,
          s.time_updated AS time_updated,
          p.worktree AS worktree
        FROM session s
        LEFT JOIN project p ON p.id = s.project_id
        WHERE s.time_archived IS NULL
          AND (? IS NULL OR COALESCE(s.time_updated, s.time_created, 0) >= ?)
        ORDER BY COALESCE(s.time_updated, s.time_created, 0) DESC, s.id DESC
        ${limitClause}
      `).all(...params);
            let processed = 0;
            let firstSessionId = null;
            for (const row of rows) {
                const indexedSessionId = this.upsertSession(db, row);
                if (!indexedSessionId) {
                    continue;
                }
                if (!firstSessionId) {
                    firstSessionId = indexedSessionId;
                }
                processed += 1;
            }
            return { processed, firstSessionId };
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            console.warn('[OpenCodeProvider] Failed to synchronize sessions:', message);
            return { processed: 0, firstSessionId: null };
        }
        finally {
            db.close();
        }
    }
    upsertSession(db, row) {
        const sessionId = readOptionalString(row.id);
        const projectPath = readOptionalString(row.directory) ?? readOptionalString(row.worktree);
        if (!sessionId || !projectPath) {
            return null;
        }
        const fallbackTitle = 'Untitled OpenCode Session';
        const existingSession = sessionsDb.getSessionById(sessionId);
        const existingName = existingSession?.custom_name;
        const nextName = existingName && existingName !== fallbackTitle
            ? existingName
            : readOptionalString(row.title) ?? this.readFirstUserText(db, sessionId);
        // OpenCode stores every session in one shared sqlite database, so jsonl_path
        // must stay null to avoid deleting opencode.db when one app session is removed.
        sessionsDb.createSession(sessionId, this.provider, projectPath, normalizeSessionName(nextName, fallbackTitle), normalizeProviderTimestamp(row.time_created), normalizeProviderTimestamp(row.time_updated ?? row.time_created), null);
        return sessionId;
    }
    readFirstUserText(db, sessionId) {
        try {
            const row = db.prepare(`
        SELECT p.data AS data
        FROM message m
        INNER JOIN part p
          ON p.session_id = m.session_id
         AND p.message_id = m.id
        WHERE m.session_id = ?
          AND json_extract(m.data, '$.role') = 'user'
          AND json_extract(p.data, '$.type') = 'text'
        ORDER BY COALESCE(m.time_created, 0), COALESCE(p.time_created, 0)
        LIMIT 1
      `).get(sessionId);
            const data = readJsonRecord(row?.data);
            return readOptionalString(data?.text);
        }
        catch {
            return undefined;
        }
    }
}
//# sourceMappingURL=opencode-session-synchronizer.provider.js.map