"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.listAgents = listAgents;
exports.getAgent = getAgent;
exports.createAgent = createAgent;
exports.updateAgent = updateAgent;
exports.deleteAgent = deleteAgent;
exports.seedAgent = seedAgent;
exports.getAgentStats = getAgentStats;
const db_1 = require("../../lib/db");
const logger_1 = require("../../lib/logger");
const publish_1 = require("../../lib/events/publish");
const sql_1 = require("./sql");
async function listAgents(filters = {}) {
    const pool = (0, db_1.getPool)();
    const limit = filters.limit ?? 50;
    const offset = filters.offset ?? 0;
    const status = filters.status ?? null;
    const domain = filters.knowledge_domain ?? null;
    const [dataRes, countRes] = await Promise.all([
        pool.query(sql_1.LIST_AGENTS, [status, domain, limit, offset]),
        pool.query(sql_1.COUNT_AGENTS, [status, domain]),
    ]);
    return {
        agents: dataRes.rows,
        total: countRes.rows[0]?.total ?? 0,
    };
}
async function getAgent(id) {
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.GET_AGENT, [id]);
    return rows[0] ?? null;
}
async function createAgent(data) {
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.INSERT_AGENT, [
        data.id,
        data.description ?? null,
        data.status ?? 'inactive',
        data.user_id ?? null,
        data.knowledge_domain ?? null,
        JSON.stringify(data.capabilities ?? []),
        JSON.stringify(data.behaviors ?? {}),
        data.goals ?? null,
        data.rules ?? null,
        data.workflow_type ?? null,
        data.pipeline_id ?? null,
        JSON.stringify(data.metadata ?? {}),
    ]);
    return rows[0];
}
async function updateAgent(id, data) {
    const pool = (0, db_1.getPool)();
    // Check current status before update for change detection
    const oldAgent = data.status ? await getAgent(id) : null;
    const { rows } = await pool.query(sql_1.UPDATE_AGENT, [
        id,
        data.description ?? null,
        data.status ?? null,
        data.user_id ?? null,
        data.knowledge_domain ?? null,
        data.capabilities ? JSON.stringify(data.capabilities) : null,
        data.behaviors ? JSON.stringify(data.behaviors) : null,
        data.goals ?? null,
        data.rules ?? null,
        data.workflow_type ?? null,
        data.pipeline_id ?? null,
        data.metadata ? JSON.stringify(data.metadata) : null,
        data.last_run_at ?? null,
    ]);
    const updated = rows[0] ?? null;
    if (updated && oldAgent && data.status && oldAgent.status !== updated.status) {
        (0, publish_1.publishAgentEvent)({
            type: 'agent.status_changed',
            agentId: updated.id,
            agentName: updated.id,
            status: updated.status,
            data: { previous: oldAgent.status },
        });
    }
    // Restart event triggers and cron schedules if status or behaviors changed
    if (updated && (data.status || data.behaviors)) {
        Promise.resolve().then(() => __importStar(require('./trigger-registry'))).then(({ agentTriggerRegistry }) => agentTriggerRegistry.restartAgent(id)).catch(() => { });
        Promise.resolve().then(() => __importStar(require('../cron'))).then(({ cronRegistry }) => cronRegistry.restartAgentCrons(updated)).catch(() => { });
        // Signal other containers to re-arm triggers for this agent
        (0, publish_1.publishAgentEvent)({
            type: 'agent.triggers_changed',
            agentId: id,
            agentName: id,
            data: { action: 'updated' },
        });
    }
    return updated;
}
async function deleteAgent(id) {
    // Stop event triggers and cron schedules before deleting
    Promise.resolve().then(() => __importStar(require('./trigger-registry'))).then(({ agentTriggerRegistry }) => agentTriggerRegistry.stopAgent(id)).catch(() => { });
    Promise.resolve().then(() => __importStar(require('../cron'))).then(({ cronRegistry }) => cronRegistry.stopAgentCrons(id)).catch(() => { });
    // Signal other containers to stop triggers for this agent
    (0, publish_1.publishAgentEvent)({
        type: 'agent.triggers_changed',
        agentId: id,
        agentName: id,
        data: { action: 'deleted' },
    });
    const pool = (0, db_1.getPool)();
    const { rowCount } = await pool.query(sql_1.DELETE_AGENT, [id]);
    return (rowCount ?? 0) > 0;
}
/**
 * Seed an agent at startup (insert-if-absent).
 * DB is the source of truth — if the row already exists, log drift warnings
 * but do not overwrite.
 */
async function seedAgent(data) {
    const pool = (0, db_1.getPool)();
    const { rowCount } = await pool.query(sql_1.SEED_AGENT, [
        data.id,
        data.description ?? null,
        data.status ?? 'inactive',
        data.user_id ?? null,
        data.knowledge_domain ?? null,
        JSON.stringify(data.capabilities ?? []),
        JSON.stringify(data.behaviors ?? {}),
        data.goals ?? null,
        data.rules ?? null,
        data.workflow_type ?? null,
        data.pipeline_id ?? null,
        JSON.stringify(data.metadata ?? {}),
    ]);
    const inserted = (rowCount ?? 0) > 0;
    if (!inserted) {
        const existing = await getAgent(data.id);
        if (existing) {
            const drifts = [];
            if (data.description && existing.description !== data.description)
                drifts.push('description');
            if (data.status && existing.status !== data.status)
                drifts.push('status');
            if (data.knowledge_domain && existing.knowledge_domain !== data.knowledge_domain)
                drifts.push('knowledge_domain');
            if (drifts.length) {
                logger_1.loggerRegistry.warn(`[long-tail] agent drift: ${data.id} — ${drifts.join(', ')} differ between code and DB`);
            }
        }
    }
    return inserted;
}
/**
 * Aggregate stats for an agent: knowledge entry count, pending escalation count,
 * and last workflow execution time.
 */
async function getAgentStats(agent) {
    const pool = (0, db_1.getPool)();
    const stats = {
        knowledge_count: 0,
        escalation_count: 0,
    };
    if (agent.knowledge_domain) {
        const { rows } = await pool.query(sql_1.KNOWLEDGE_COUNT, [agent.knowledge_domain]);
        stats.knowledge_count = rows[0]?.count ?? 0;
    }
    if (agent.user_id) {
        const { rows } = await pool.query(sql_1.ESCALATION_COUNT, [agent.user_id]);
        stats.escalation_count = rows[0]?.count ?? 0;
    }
    stats.last_execution_at = agent.last_run_at ?? undefined;
    return stats;
}
