"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initBehaviorTables = initBehaviorTables;
exports.logError = logError;
exports.logErrorFix = logErrorFix;
exports.getErrorPatterns = getErrorPatterns;
exports.getRecentErrors = getRecentErrors;
exports.logDecision = logDecision;
exports.getDecisions = getDecisions;
exports.logContext = logContext;
exports.getCurrentContext = getCurrentContext;
exports.logStuck = logStuck;
exports.logStuckResolved = logStuckResolved;
exports.getStuckPatterns = getStuckPatterns;
exports.getBehaviorSummary = getBehaviorSummary;
exports.getLastTouchedFile = getLastTouchedFile;
exports.getPatternCounts = getPatternCounts;
exports.getRecentDecisionsWithAgo = getRecentDecisionsWithAgo;
const database_1 = require("../../06-memory/database/database");
function initBehaviorTables() {
    const db = (0, database_1.getDb)();
    db.exec(`
    CREATE TABLE IF NOT EXISTS error_log (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project TEXT,
      file_path TEXT,
      error_type TEXT,
      error_message TEXT,
      line_number INTEGER,
      fix_applied TEXT,
      fix_worked INTEGER DEFAULT 0,
      time_to_fix_ms INTEGER,
      occurred_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS decision_log (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project TEXT,
      file_path TEXT,
      decision TEXT,
      approach TEXT,
      result TEXT,
      worked INTEGER DEFAULT 0,
      context TEXT,
      decided_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS context_log (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project TEXT,
      current_task TEXT,
      files_involved TEXT,
      status TEXT DEFAULT 'active',
      started_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS stuck_log (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      project TEXT,
      file_path TEXT,
      description TEXT,
      attempts INTEGER DEFAULT 1,
      resolved INTEGER DEFAULT 0,
      resolution TEXT,
      stuck_at TEXT DEFAULT (datetime('now'))
    );
  `);
}
// ─── Error Tracking ──────────────────────────────────────────────────────────
function logError(data) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const r = db.prepare('INSERT INTO error_log (project, file_path, error_type, error_message, line_number) VALUES (?, ?, ?, ?, ?)').run(data.project || '', data.file || '', data.errorType || '', data.errorMessage || '', data.line || 0);
    return { id: Number(r.lastInsertRowid) };
}
function logErrorFix(data) {
    const db = (0, database_1.getDb)();
    db.prepare('UPDATE error_log SET fix_applied = ?, fix_worked = ?, time_to_fix_ms = ? WHERE id = ?').run(data.fixApplied, data.worked ? 1 : 0, data.timeToFixMs || 0, data.errorId);
}
function getErrorPatterns(project) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const where = project ? 'WHERE project = ?' : '';
    const params = project ? [project] : [];
    return db.prepare(`
    SELECT error_type, COUNT(*) as count,
      AVG(time_to_fix_ms) as avgFixTime,
      AVG(CASE WHEN fix_worked = 1 THEN 1.0 ELSE 0.0 END) as fixRate,
      MAX(occurred_at) as lastOccurrence
    FROM error_log ${where}
    GROUP BY error_type
    ORDER BY count DESC
  `).all(...params);
}
function getRecentErrors(limit = 10, project) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const where = project ? 'WHERE project = ?' : '';
    const params = project ? [project, limit] : [limit];
    return db.prepare(`
    SELECT id, file_path as file, error_type as errorType, error_message as errorMessage,
      fix_applied as fixApplied, fix_worked as worked, occurred_at as occurredAt
    FROM error_log ${where}
    ORDER BY occurred_at DESC LIMIT ?
  `).all(...params);
}
// ─── Decision Tracking ───────────────────────────────────────────────────────
function logDecision(data) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const r = db.prepare('INSERT INTO decision_log (project, file_path, decision, approach, result, worked, context) VALUES (?, ?, ?, ?, ?, ?, ?)').run(data.project || '', data.file || '', data.decision, data.approach || '', data.result || '', data.worked ? 1 : 0, data.context || '');
    return { id: Number(r.lastInsertRowid) };
}
function getDecisions(project, limit = 20) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const where = project ? 'WHERE project = ?' : '';
    const params = project ? [project, limit] : [limit];
    return db.prepare(`
    SELECT id, file_path as file, decision, approach, result, worked, context, decided_at as decidedAt
    FROM decision_log ${where}
    ORDER BY decided_at DESC LIMIT ?
  `).all(...params);
}
// ─── Context Tracking ────────────────────────────────────────────────────────
function logContext(data) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    db.prepare('UPDATE context_log SET status = ? WHERE status = ?').run('paused', 'active');
    const r = db.prepare('INSERT INTO context_log (project, current_task, files_involved) VALUES (?, ?, ?)').run(data.project || '', data.task, JSON.stringify(data.files || []));
    return { id: Number(r.lastInsertRowid) };
}
function getCurrentContext(project) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const where = project ? 'WHERE project = ? AND status = ?' : 'WHERE status = ?';
    const params = project ? [project, 'active'] : ['active'];
    const row = db.prepare(`
    SELECT current_task as task, files_involved as files, started_at as startedAt
    FROM context_log ${where}
    ORDER BY updated_at DESC LIMIT 1
  `).get(...params);
    if (!row)
        return null;
    return { task: row.task, files: JSON.parse(row.files || '[]'), startedAt: row.startedAt };
}
// ─── Stuck Tracking ──────────────────────────────────────────────────────────
function logStuck(data) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const r = db.prepare('INSERT INTO stuck_log (project, file_path, description) VALUES (?, ?, ?)').run(data.project || '', data.file || '', data.description);
    return { id: Number(r.lastInsertRowid) };
}
function logStuckResolved(stuckId, resolution) {
    const db = (0, database_1.getDb)();
    db.prepare('UPDATE stuck_log SET resolved = 1, resolution = ? WHERE id = ?').run(resolution, stuckId);
}
function getStuckPatterns(project) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const where = project ? 'WHERE project = ?' : '';
    const params = project ? [project] : [];
    return db.prepare(`
    SELECT file_path as file, description, attempts, resolved, resolution
    FROM stuck_log ${where}
    ORDER BY stuck_at DESC LIMIT 20
  `).all(...params);
}
// ─── Summary ─────────────────────────────────────────────────────────────────
function getBehaviorSummary(project) {
    const db = (0, database_1.getDb)();
    initBehaviorTables();
    const where = project ? 'WHERE project = ?' : '';
    const params = project ? [project] : [];
    const totalErrors = db.prepare(`SELECT COUNT(*) as c FROM error_log ${where}`).get(...params).c;
    const totalDecisions = db.prepare(`SELECT COUNT(*) as c FROM decision_log ${where}`).get(...params).c;
    return {
        totalErrors,
        errorPatterns: getErrorPatterns(project),
        recentErrors: getRecentErrors(5, project),
        totalDecisions,
        recentDecisions: getDecisions(project, 5),
        currentContext: getCurrentContext(project),
        stuckIssues: getStuckPatterns(project),
    };
}
// ─── Pre-Launch Test Suite helpers ──────────────────────────────────────────
/**
 * Get the most-recently-touched file in a project, with timestamp + touch count.
 * Source of truth: session_files table (updated by live-watcher on every file_save).
 * Returns null if no files have been touched yet.
 */
function getLastTouchedFile(project) {
    const db = (0, database_1.getDb)();
    const where = project ? 'WHERE project = ?' : '';
    const params = project ? [project] : [];
    const row = db.prepare(`
    SELECT file_path as file, last_touched as lastTouched, touch_count as touchCount
    FROM session_files ${where}
    ORDER BY last_touched DESC LIMIT 1
  `).get(...params);
    if (!row)
        return null;
    return row;
}
/**
 * Count detected patterns for a project, split by category.
 * Mirrors what the @cell block displays under "Patterns detected: N".
 */
function getPatternCounts(project) {
    try {
        const db = (0, database_1.getDb)();
        const where = project ? 'WHERE project = ?' : '';
        const params = project ? [project] : [];
        const rows = db.prepare(`
      SELECT category, COUNT(*) as cnt
      FROM code_patterns ${where}
      GROUP BY category
    `).all(...params);
        const byCategory = {};
        let total = 0;
        for (const r of rows) {
            byCategory[r.category || 'unknown'] = Number(r.cnt);
            total += Number(r.cnt);
        }
        return { total, byCategory };
    }
    catch {
        return { total: 0, byCategory: {} };
    }
}
/**
 * Get the most recent decisions for a project (with formatted "X minutes ago" string).
 * Default limit 5 — matches what `cell status --decisions` displays.
 */
function getRecentDecisionsWithAgo(project, limit = 5) {
    const rows = getDecisions(project, limit);
    const now = Date.now();
    return rows.map(r => {
        // SQLite datetime('now') returns UTC; append Z so JS parses as UTC, not local
        const ts = parseSqliteUtc(r.decidedAt);
        const diffMs = now - ts;
        return {
            id: r.id,
            file: r.file,
            decision: r.decision,
            // SQLite returns worked as 0/1 integer; coerce to boolean
            worked: Boolean(r.worked),
            ago: formatAgo(diffMs),
            decidedAt: r.decidedAt,
        };
    });
}
function formatAgo(ms) {
    if (ms < 0)
        return 'just now';
    const sec = Math.floor(ms / 1000);
    if (sec < 60)
        return `${sec} second${sec === 1 ? '' : 's'} ago`;
    const min = Math.floor(sec / 60);
    if (min < 60)
        return `${min} minute${min === 1 ? '' : 's'} ago`;
    const hr = Math.floor(min / 60);
    if (hr < 24)
        return `${hr} hour${hr === 1 ? '' : 's'} ago`;
    const day = Math.floor(hr / 24);
    if (day < 30)
        return `${day} day${day === 1 ? '' : 's'} ago`;
    const month = Math.floor(day / 30);
    return `${month} month${month === 1 ? '' : 's'} ago`;
}
/**
 * Parse a SQLite `datetime('now')` string (UTC, no TZ marker) into JS ms.
 * Without this helper, `new Date(str)` interprets SQLite datetimes as LOCAL time,
 * producing a 5h30m offset in IST.
 */
function parseSqliteUtc(s) {
    if (!s)
        return 0;
    if (s.endsWith('Z') || /[+-]\d{2}:?\d{2}$/.test(s)) {
        return new Date(s).getTime();
    }
    return new Date(s.replace(' ', 'T') + 'Z').getTime();
}
// test touch 14:50:07
//# sourceMappingURL=behavioral-tracker.js.map