"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildExecution = buildExecution;
const db_1 = require("../../lib/db");
const hotmesh_utils_1 = require("../hotmesh-utils");
const enrichment_1 = require("./enrichment");
const events_1 = require("./events");
const sql_1 = require("./sql");
/**
 * Build a complete execution export for a YAML engine workflow job.
 *
 * Pipeline:
 *   1. Load job record and inflate symbolic attributes
 *   2. Extract metadata and activity hierarchy
 *   3. Enrich activities with input data from stream history
 *   4. Construct chronological event timeline
 *   5. Assemble final export with summary statistics
 */
async function buildExecution(jobId, appId, schema) {
    // 1. Load and inflate
    const ctx = await loadJobContext(jobId, appId, schema);
    // 2. Enrich activity inputs
    const inputByNameDim = await (0, enrichment_1.fetchActivityInputs)(jobId, appId);
    // 3. Build event timeline
    const events = (0, events_1.buildEvents)(ctx, inputByNameDim);
    // 4. Fetch structured activity details (for cycle/dimension visualization)
    const activities = inputByNameDim.size > 0
        ? await (0, enrichment_1.fetchActivityDetails)(jobId, appId)
        : undefined;
    // 5. Assemble export
    return assembleExport(ctx, events, activities);
}
// ── Job loading ──────────────────────────────────────────────────────────────
async function loadJobContext(jobId, appId, schema) {
    const jobKey = `hmsh:${appId}:j:${jobId}`;
    const pool = (0, db_1.getPool)();
    const [jobResult, symbolMap] = await Promise.all([
        pool.query((0, sql_1.GET_JOB)(schema), [jobKey]),
        (0, hotmesh_utils_1.loadSymbolMap)(schema, appId),
    ]);
    if (jobResult.rows.length === 0) {
        const err = new Error(`No job found for id "${jobId}" in schema "${appId}"`);
        err.status = 404;
        throw err;
    }
    const job = jobResult.rows[0];
    const attrRows = await pool.query((0, sql_1.GET_JOB_ATTRIBUTES)(schema), [job.id]);
    const rawAttrs = {};
    for (const row of attrRows.rows) {
        const field = row.dimension ? `${row.symbol}${row.dimension}` : row.symbol;
        rawAttrs[field] = row.value;
    }
    const hierarchy = (0, hotmesh_utils_1.restoreHierarchy)((0, hotmesh_utils_1.inflateAttributes)(rawAttrs, symbolMap));
    const meta = hierarchy['metadata'];
    return {
        jobId,
        appId,
        job,
        startTime: meta?.['jc'] ? (0, hotmesh_utils_1.hmshTimestampToISO)(meta['jc']) : job.created_at?.toISOString(),
        closeTime: meta?.['ju'] ? (0, hotmesh_utils_1.hmshTimestampToISO)(meta['ju']) : job.updated_at?.toISOString(),
        traceId: meta?.['trc'] || null,
        workflowTopic: meta?.['tpc'] || job.entity || null,
        workflowName: meta?.['aid'] || meta?.['tpc'] || job.entity || null,
        workflowResult: hierarchy['data'] || null,
        metadata: meta,
        activities: (0, hotmesh_utils_1.extractActivities)(hierarchy),
    };
}
// ── Assembly ─────────────────────────────────────────────────────────────────
function assembleExport(ctx, events, activities) {
    const triggerCount = ctx.activities.filter((a) => a.type === 'trigger').length;
    const workerCount = ctx.activities.filter((a) => a.type !== 'trigger').length;
    const completed = events.filter((e) => e.event_type === 'activity_task_completed').length;
    const failed = events.filter((e) => e.event_type === 'activity_task_failed').length;
    // Derive close_time from the last event when available — meta.ju (job updated)
    // often equals meta.jc (job created), producing 0ms duration.
    const lastEventTime = events.length > 0 ? events[events.length - 1].event_time : null;
    const closeTime = lastEventTime || ctx.closeTime || null;
    const startTime = ctx.startTime || null;
    let durationMs = null;
    if (startTime && closeTime) {
        const diff = new Date(closeTime).getTime() - new Date(startTime).getTime();
        if (diff >= 0)
            durationMs = diff;
    }
    return {
        workflow_id: ctx.jobId,
        workflow_type: ctx.workflowTopic,
        workflow_name: ctx.workflowName,
        task_queue: ctx.appId,
        status: ctx.job.status > 0 ? 'running' : ctx.job.status === 0 ? 'completed' : 'failed',
        start_time: startTime,
        close_time: closeTime,
        duration_ms: durationMs,
        trace_id: ctx.traceId,
        result: ctx.workflowResult,
        events,
        activities,
        summary: {
            total_events: events.length,
            activities: { total: ctx.activities.length, completed, failed, system: triggerCount, user: workerCount },
            child_workflows: { total: 0, completed: 0, failed: 0 },
            timers: 0,
            signals: 0,
        },
    };
}
