"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.buildMergedYaml = buildMergedYaml;
exports.recompileWithContext = recompileWithContext;
// eslint-disable-next-line @typescript-eslint/no-var-requires
const yaml = require('js-yaml');
const defaults_1 = require("../../modules/defaults");
const logger_1 = require("../../lib/logger");
const yamlDb = __importStar(require("./db"));
/**
 * Merge all YAML graphs for an app_id into a single YAML document.
 * HotMesh supports multiple graphs in one app definition under `app.graphs[]`.
 */
async function buildMergedYaml(appId, version) {
    const workflows = await yamlDb.listYamlWorkflowsByAppId(appId);
    if (workflows.length === 0) {
        throw new Error(`No YAML workflows found for app_id: ${appId}`);
    }
    const allGraphs = [];
    for (const wf of workflows) {
        const parsed = yaml.load(wf.yaml_content);
        if (parsed?.app?.graphs) {
            allGraphs.push(...parsed.app.graphs);
        }
    }
    // Resolve duplicate activity IDs across graphs by rewriting suffixes
    const activityIds = new Set();
    for (const graph of allGraphs) {
        const g = graph;
        if (!g.activities)
            continue;
        // Check if any activity IDs collide with previously seen IDs
        const ids = Object.keys(g.activities);
        const hasCollision = ids.some((id) => activityIds.has(id));
        if (hasCollision) {
            // Rewrite all activity IDs in this graph with a unique suffix
            const newSuffix = Math.random().toString(36).slice(2, 6);
            const oldSuffix = extractSuffix(ids[0]);
            if (oldSuffix) {
                rewriteGraphSuffix(g, oldSuffix, newSuffix);
                logger_1.loggerRegistry.info(`[yaml-workflow] rewrote activity suffix ${oldSuffix}→${newSuffix} in "${g.subscribes}" to resolve collision`);
            }
        }
        // Register all (possibly rewritten) activity IDs
        for (const id of Object.keys(g.activities)) {
            activityIds.add(id);
        }
    }
    const merged = {
        app: {
            id: appId,
            version,
            graphs: allGraphs,
        },
    };
    return yaml.dump(merged, { lineWidth: defaults_1.YAML_LINE_WIDTH, noRefs: true, sortKeys: false });
}
/** Extract the 4-char suffix from an activity ID like "trigger_x8kf" */
function extractSuffix(activityId) {
    const match = activityId.match(/_([a-z0-9]{4})$/);
    return match ? match[1] : null;
}
/** Rewrite all activity ID suffixes in a graph definition */
function rewriteGraphSuffix(graph, oldSuffix, newSuffix) {
    const suffixPattern = new RegExp(`_${oldSuffix}\\b`, 'g');
    const replace = (obj) => {
        if (typeof obj === 'string')
            return obj.replace(suffixPattern, `_${newSuffix}`);
        if (Array.isArray(obj))
            return obj.map(replace);
        if (obj && typeof obj === 'object') {
            const result = {};
            for (const [k, v] of Object.entries(obj)) {
                const newKey = k.replace(suffixPattern, `_${newSuffix}`);
                result[newKey] = replace(v);
            }
            return result;
        }
        return obj;
    };
    if (graph.activities)
        graph.activities = replace(graph.activities);
    if (graph.transitions)
        graph.transitions = replace(graph.transitions);
    if (graph.hooks)
        graph.hooks = replace(graph.hooks);
}
/**
 * Re-run the compilation pipeline for the most recently compiled workflow
 * in the app, feeding the deployment error as context so the LLM can
 * produce a plan that avoids the same issue.
 *
 * Returns true if recompilation succeeded and the DB was updated, false otherwise.
 */
async function recompileWithContext(appId, failedYaml, errorMessage) {
    try {
        // Find the most recently updated non-archived workflow for this app_id
        const workflows = await yamlDb.listYamlWorkflowsByAppId(appId);
        // Sort by updated_at desc to find the one that likely triggered the failure
        const sorted = workflows.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
        const target = sorted[0];
        if (!target?.source_workflow_id) {
            logger_1.loggerRegistry.warn('[yaml-workflow] recompilation skipped: no source workflow to recompile from');
            return false;
        }
        logger_1.loggerRegistry.info(`[yaml-workflow] recompiling "${target.name}" (source: ${target.source_workflow_id}) with error context`);
        const { generateYamlFromExecution } = await Promise.resolve().then(() => __importStar(require('./generator')));
        const result = await generateYamlFromExecution({
            workflowId: target.source_workflow_id,
            taskQueue: 'long-tail-system',
            workflowName: 'mcpQuery',
            name: target.name,
            description: target.description || undefined,
            appId: target.app_id,
            subscribes: target.graph_topic,
            priorDeployError: errorMessage,
            priorFailedYaml: failedYaml,
        });
        // Update the workflow record with the recompiled YAML
        await yamlDb.updateYamlWorkflow(target.id, {
            yaml_content: result.yaml,
            activity_manifest: result.activityManifest,
        });
        logger_1.loggerRegistry.info(`[yaml-workflow] recompilation complete for "${target.name}" (${result.yaml.length} chars)`);
        return true;
    }
    catch (err) {
        logger_1.loggerRegistry.warn(`[yaml-workflow] recompilation failed: ${err.message}`);
        return false;
    }
}
