"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWorkflowSet = createWorkflowSet;
exports.listWorkflowSets = listWorkflowSets;
exports.getWorkflowSet = getWorkflowSet;
exports.updateWorkflowSetPlanApi = updateWorkflowSetPlanApi;
exports.buildWorkflowSet = buildWorkflowSet;
exports.deployWorkflowSet = deployWorkflowSet;
exports.addToWorkflowSet = addToWorkflowSet;
const workflow_sets_1 = require("../services/workflow-sets");
const insight_1 = require("../services/insight");
const yaml_workflows_1 = require("./yaml-workflows");
/**
 * Create a new workflow set and kick off the LLM-powered planner.
 *
 * Persists the workflow set record, then starts an async planner workflow
 * that generates the plan from the specification. Requires at least one
 * LLM API key (OPENAI_API_KEY or ANTHROPIC_API_KEY) to be configured.
 * Returns 409 if a workflow set with the same name already exists.
 *
 * @param input.name — unique name for the workflow set (required)
 * @param input.description — optional description of the workflow set
 * @param input.specification — free-text specification the planner uses to generate workflows (required)
 * @param auth — authenticated user context; userId is forwarded to the planner
 * @returns `{ status: 201, data: { ...set, source_workflow_id, planner_workflow_id } }` the created set with planner IDs
 */
async function createWorkflowSet(input, auth) {
    try {
        if (!input.specification || typeof input.specification !== 'string') {
            return { status: 400, error: 'specification is required' };
        }
        if (!input.name || typeof input.name !== 'string') {
            return { status: 400, error: 'name is required' };
        }
        if (!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
            return { status: 503, error: 'Workflow planner requires an LLM API key' };
        }
        const set = await (0, workflow_sets_1.createWorkflowSet)({
            name: input.name,
            description: input.description,
            specification: input.specification,
        });
        const plannerResult = await (0, insight_1.startWorkflowPlanner)({
            specification: input.specification,
            setId: set.id,
            wait: false,
            userId: auth?.userId,
        });
        await (0, workflow_sets_1.updateWorkflowSetSourceWorkflow)(set.id, plannerResult.workflow_id);
        return {
            status: 201,
            data: {
                ...set,
                source_workflow_id: plannerResult.workflow_id,
                planner_workflow_id: plannerResult.workflow_id,
            },
        };
    }
    catch (err) {
        if (err.code === '23505') {
            return { status: 409, error: 'A workflow set with this name already exists' };
        }
        return { status: 500, error: err.message };
    }
}
/**
 * List workflow sets with optional filtering and pagination.
 *
 * @param input.status — filter by workflow set status
 * @param input.search — free-text search term to match against set names or descriptions
 * @param input.limit — maximum number of results to return
 * @param input.offset — number of results to skip for pagination
 * @returns `{ status: 200, data: WorkflowSet[] }` paginated list of workflow sets
 */
async function listWorkflowSets(input) {
    try {
        const result = await (0, workflow_sets_1.listWorkflowSets)({
            status: input.status,
            search: input.search,
            limit: input.limit,
            offset: input.offset,
        });
        return { status: 200, data: result };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Retrieve a single workflow set by ID.
 *
 * @param input.id — unique identifier of the workflow set
 * @returns `{ status: 200, data: WorkflowSet }` the workflow set record, or 404 if not found
 */
async function getWorkflowSet(input) {
    try {
        const set = await (0, workflow_sets_1.getWorkflowSet)(input.id);
        if (!set) {
            return { status: 404, error: 'Workflow set not found' };
        }
        return { status: 200, data: set };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Replace the plan and optional namespaces on a workflow set.
 *
 * @param input.id — unique identifier of the workflow set to update
 * @param input.plan — array of plan entries (required, must be an array)
 * @param input.namespaces — optional array of namespace definitions associated with the plan
 * @returns `{ status: 200, data: WorkflowSet }` the updated workflow set, or 404 if not found
 */
async function updateWorkflowSetPlanApi(input) {
    try {
        if (!Array.isArray(input.plan)) {
            return { status: 400, error: 'plan must be an array' };
        }
        const updated = await (0, workflow_sets_1.updateWorkflowSetPlan)(input.id, input.plan, input.namespaces || []);
        if (!updated) {
            return { status: 404, error: 'Workflow set not found' };
        }
        return { status: 200, data: updated };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Transition a workflow set from "planned" to "building" status.
 *
 * Returns 409 if the set is not currently in "planned" status.
 *
 * @param input.id — unique identifier of the workflow set to build
 * @returns `{ status: 200, data: { status: 'building', id } }` confirmation the build has started
 */
async function buildWorkflowSet(input) {
    try {
        const set = await (0, workflow_sets_1.getWorkflowSet)(input.id);
        if (!set) {
            return { status: 404, error: 'Workflow set not found' };
        }
        if (set.status !== 'planned') {
            return { status: 409, error: `Cannot build set in '${set.status}' status` };
        }
        await (0, workflow_sets_1.updateWorkflowSetStatus)(input.id, 'building');
        return { status: 200, data: { status: 'building', id: input.id } };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Transition a workflow set to "deploying" status.
 *
 * @param input.id — unique identifier of the workflow set to deploy
 * @returns `{ status: 200, data: { status: 'deploying', id } }` confirmation the deploy has started
 */
async function deployWorkflowSet(input) {
    try {
        const set = await (0, workflow_sets_1.getWorkflowSet)(input.id);
        if (!set) {
            return { status: 404, error: 'Workflow set not found' };
        }
        await (0, workflow_sets_1.updateWorkflowSetStatus)(input.id, 'deploying');
        return { status: 200, data: { status: 'deploying', id: input.id } };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
/**
 * Add additional workflows to an existing set.
 *
 * Invokes the planner with the new specification and existing set context.
 * The planner appends new plan items (offset build_order) and builds them
 * with sibling schema awareness so composition wiring works.
 */
async function addToWorkflowSet(input, auth) {
    try {
        if (!input.specification || typeof input.specification !== 'string') {
            return { status: 400, error: 'specification is required' };
        }
        if (!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
            return { status: 503, error: 'Workflow planner requires an LLM API key' };
        }
        const set = await (0, workflow_sets_1.getWorkflowSet)(input.id);
        if (!set) {
            return { status: 404, error: 'Workflow set not found' };
        }
        // Gather existing plan items and built workflow schemas
        const existingPlan = (set.plan || []).map(p => ({
            name: p.name,
            description: p.description,
            namespace: p.namespace,
        }));
        const yamlResult = await (0, yaml_workflows_1.listYamlWorkflows)({ set_id: input.id, limit: 100 });
        const workflows = yamlResult.data?.workflows || [];
        const existingSchemas = workflows
            .filter((w) => w.status === 'active' || w.status === 'draft')
            .map((w) => ({
            name: w.name,
            input_schema: w.input_schema || {},
            output_schema: w.output_schema || {},
            graph_topic: w.graph_topic,
        }));
        // Append the new spec to the set's specification field so the full
        // history of what was pasted is preserved and visible on step 1.
        await (0, workflow_sets_1.appendWorkflowSetSpecification)(input.id, input.specification);
        const plannerResult = await (0, insight_1.startWorkflowPlanner)({
            specification: input.specification,
            setId: input.id,
            wait: false,
            userId: auth?.userId,
            existingPlan,
            existingSchemas,
        });
        await (0, workflow_sets_1.updateWorkflowSetSourceWorkflow)(input.id, plannerResult.workflow_id);
        return {
            status: 200,
            data: {
                ...set,
                source_workflow_id: plannerResult.workflow_id,
                planner_workflow_id: plannerResult.workflow_id,
            },
        };
    }
    catch (err) {
        return { status: 500, error: err.message };
    }
}
