"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.upsertWorkflowConfig = upsertWorkflowConfig;
exports.deleteWorkflowConfig = deleteWorkflowConfig;
exports.seedWorkflowConfig = seedWorkflowConfig;
const db_1 = require("../../lib/db");
const read_1 = require("./read");
const logger_1 = require("../../lib/logger");
const sql_1 = require("./sql");
async function upsertWorkflowConfig(config) {
    const pool = (0, db_1.getPool)();
    const client = await pool.connect();
    try {
        await client.query('BEGIN');
        // Ensure all referenced roles exist in lt_roles (FK constraints)
        const allRoles = new Set([
            config.default_role,
            ...config.roles,
            ...config.invocation_roles,
        ]);
        for (const role of allRoles) {
            await client.query(sql_1.ENSURE_ROLE_EXISTS, [role]);
        }
        // Upsert the workflow row
        await client.query(sql_1.UPSERT_WORKFLOW, [
            config.workflow_type,
            config.invocable,
            config.task_queue,
            config.default_role,
            config.description,
            config.consumes,
            config.envelope_schema ?? null,
            config.resolver_schema ?? null,
            config.cron_schedule ?? null,
            config.tool_tags || [],
            config.execute_as ?? null,
        ]);
        // Replace roles
        await client.query(sql_1.DELETE_CONFIG_ROLES, [config.workflow_type]);
        for (const role of config.roles) {
            await client.query(sql_1.INSERT_CONFIG_ROLE, [config.workflow_type, role]);
        }
        // Replace invocation roles
        await client.query(sql_1.DELETE_INVOCATION_ROLES, [config.workflow_type]);
        for (const role of config.invocation_roles) {
            await client.query(sql_1.INSERT_INVOCATION_ROLE, [config.workflow_type, role]);
        }
        await client.query('COMMIT');
    }
    catch (err) {
        await client.query('ROLLBACK');
        throw err;
    }
    finally {
        client.release();
    }
    return (await (0, read_1.getWorkflowConfig)(config.workflow_type));
}
async function deleteWorkflowConfig(workflowType) {
    const pool = (0, db_1.getPool)();
    const { rowCount } = await pool.query(sql_1.DELETE_WORKFLOW, [workflowType]);
    return (rowCount ?? 0) > 0;
}
/**
 * Seed a workflow config at startup (insert-if-absent).
 * DB is the source of truth — if the row already exists, log drift warnings
 * but do not overwrite. Returns true if inserted, false if already existed.
 */
async function seedWorkflowConfig(config) {
    const pool = (0, db_1.getPool)();
    // Ensure referenced roles exist
    const allRoles = new Set([
        config.default_role,
        ...config.roles,
        ...config.invocation_roles,
    ]);
    for (const role of allRoles) {
        await pool.query(sql_1.ENSURE_ROLE_EXISTS, [role]);
    }
    // Insert-if-absent
    const { rowCount } = await pool.query(sql_1.SEED_WORKFLOW_CONFIG, [
        config.workflow_type,
        config.invocable,
        config.task_queue,
        config.default_role,
        config.description,
        config.consumes,
        config.envelope_schema ?? null,
        config.resolver_schema ?? null,
        config.cron_schedule ?? null,
        config.tool_tags || [],
        config.execute_as ?? null,
    ]);
    const inserted = (rowCount ?? 0) > 0;
    if (inserted) {
        // Seed roles (also insert-if-absent)
        for (const role of config.roles) {
            await pool.query(sql_1.SEED_CONFIG_ROLE, [config.workflow_type, role]);
        }
        for (const role of config.invocation_roles) {
            await pool.query(sql_1.SEED_INVOCATION_ROLE, [config.workflow_type, role]);
        }
    }
    else {
        // Drift detection — compare key fields
        const existing = await (0, read_1.getWorkflowConfig)(config.workflow_type);
        if (existing) {
            const drifts = [];
            if (config.description && existing.description !== config.description)
                drifts.push('description');
            if (config.invocable !== existing.invocable)
                drifts.push('invocable');
            if (config.default_role !== existing.default_role)
                drifts.push('default_role');
            if (JSON.stringify(config.envelope_schema) !== JSON.stringify(existing.envelope_schema))
                drifts.push('envelope_schema');
            if (JSON.stringify(config.resolver_schema) !== JSON.stringify(existing.resolver_schema))
                drifts.push('resolver_schema');
            if (drifts.length) {
                logger_1.loggerRegistry.warn(`[long-tail] config drift: ${config.workflow_type} — ${drifts.join(', ')} differ between code and DB`);
            }
        }
    }
    return inserted;
}
