"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.createHumanQueueServer = createHumanQueueServer;
exports.getServer = getServer;
exports.stopServer = stopServer;
const crypto = __importStar(require("crypto"));
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const logger_1 = require("../../lib/logger");
const escalationService = __importStar(require("../../services/escalation"));
const human_queue_schemas_1 = require("./human-queue-schemas");
let server = null;
/**
 * Create the Long Tail Human Queue MCP server.
 *
 * Registers five tools that expose the escalation API:
 * - escalate_to_human — create a new escalation (fire-and-forget)
 * - check_resolution — check escalation status
 * - get_available_work — list available escalations by role
 * - claim_and_resolve — claim + resolve in one step
 * - escalate_and_wait — create escalation and return signal for durable wait
 *
 * The server is created with tools registered but no transport
 * auto-connected. Callers connect a transport programmatically
 * or via the Streamable HTTP endpoint.
 */
async function createHumanQueueServer(options) {
    if (server)
        return server;
    const name = options?.name || 'long-tail-human-queue';
    server = new mcp_js_1.McpServer({ name, version: '1.0.0' });
    // ── escalate_to_human ───────────────────────────────────────────────
    server.registerTool('escalate_to_human', {
        title: 'Escalate to Human',
        description: 'Create a new escalation for human review. Returns the escalation ID.',
        inputSchema: human_queue_schemas_1.escalateSchema,
    }, async (args) => {
        const escalation = await escalationService.createEscalation({
            type: args.type || 'mcp',
            subtype: args.subtype || 'tool_call',
            description: args.message,
            priority: args.priority,
            role: args.role,
            envelope: JSON.stringify(args.data || {}),
            metadata: { source: 'mcp_server' },
        });
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        escalation_id: escalation.id,
                        status: escalation.status,
                        role: escalation.role,
                        created_at: escalation.created_at,
                    }),
                }],
        };
    });
    // ── check_resolution ────────────────────────────────────────────────
    server.registerTool('check_resolution', {
        title: 'Check Escalation Resolution',
        description: 'Check the status of an escalation. Returns status and resolver payload if resolved.',
        inputSchema: human_queue_schemas_1.checkResolutionSchema,
    }, async (args) => {
        const escalation = await escalationService.getEscalation(args.escalation_id);
        if (!escalation) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Escalation not found' }),
                    }],
                isError: true,
            };
        }
        const result = {
            escalation_id: escalation.id,
            status: escalation.status,
        };
        if (escalation.status === 'resolved' && escalation.resolver_payload) {
            try {
                result.resolver_payload = JSON.parse(escalation.resolver_payload);
            }
            catch {
                result.resolver_payload = escalation.resolver_payload;
            }
            result.resolved_at = escalation.resolved_at;
        }
        return {
            content: [{ type: 'text', text: JSON.stringify(result) }],
        };
    });
    // ── get_available_work ──────────────────────────────────────────────
    server.registerTool('get_available_work', {
        title: 'Get Available Work',
        description: 'List available escalations for a role. Returns pending, unassigned escalations.',
        inputSchema: human_queue_schemas_1.getAvailableWorkSchema,
    }, async (args) => {
        const { escalations } = await escalationService.listAvailableEscalations({
            role: args.role,
            limit: args.limit,
        });
        const items = escalations.map((e) => ({
            escalation_id: e.id,
            type: e.type,
            subtype: e.subtype,
            description: e.description,
            priority: e.priority,
            role: e.role,
            created_at: e.created_at,
        }));
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({ count: items.length, escalations: items }),
                }],
        };
    });
    // ── claim_and_resolve ───────────────────────────────────────────────
    server.registerTool('claim_and_resolve', {
        title: 'Claim and Resolve',
        description: 'Claim an escalation and immediately resolve it with a payload. Atomic operation.',
        inputSchema: human_queue_schemas_1.claimAndResolveSchema,
    }, async (args) => {
        const claimed = await escalationService.claimEscalation(args.escalation_id, args.resolver_id, 5);
        if (!claimed) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Escalation not available for claim' }),
                    }],
                isError: true,
            };
        }
        const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload);
        if (!resolved) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Failed to resolve escalation' }),
                    }],
                isError: true,
            };
        }
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        escalation_id: resolved.id,
                        status: resolved.status,
                        resolved_at: resolved.resolved_at,
                    }),
                }],
        };
    });
    // ── resolve_escalation ──────────────────────────────────────────────
    server.registerTool('resolve_escalation', {
        title: 'Resolve Escalation',
        description: 'Resolve an already-claimed escalation with a payload. Use when the claim happened externally (e.g. via API).',
        inputSchema: human_queue_schemas_1.resolveEscalationSchema,
    }, async (args) => {
        const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload);
        if (!resolved) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Failed to resolve escalation' }),
                    }],
                isError: true,
            };
        }
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        escalation_id: resolved.id,
                        status: resolved.status,
                        resolved_at: resolved.resolved_at,
                    }),
                }],
        };
    });
    // ── escalate_and_wait ──────────────────────────────────────────────
    server.registerTool('escalate_and_wait', {
        title: 'Escalate and Wait',
        description: 'Create an escalation and pause the workflow until a human responds. ' +
            'Returns a signal ID that the workflow uses to wait. ' +
            'Preferred over escalate_to_human + check_resolution polling.',
        inputSchema: human_queue_schemas_1.escalateAndWaitSchema,
    }, async (args) => {
        const signalId = `wait-for-human-${crypto.randomUUID()}`;
        // YAML workflows inject _yaml_signal_routing to override Durable's signalId-based routing
        const yamlRouting = args._yaml_signal_routing;
        const signalRouting = yamlRouting
            ? { ...yamlRouting, signalId }
            : { signalId };
        const metadata = {
            source: 'mcp_server',
            signal_routing: signalRouting,
        };
        if (args.form_schema) {
            metadata.form_schema = args.form_schema;
        }
        const escalation = await escalationService.createEscalation({
            type: args.type || 'mcp',
            subtype: args.subtype || 'wait_for_human',
            description: args.message,
            priority: args.priority,
            role: args.role,
            envelope: JSON.stringify(args.data || {}),
            metadata,
            // YAML routing provides workflow context for dashboard visibility
            workflow_type: yamlRouting?.workflowType,
            workflow_id: yamlRouting?.workflowId,
            task_queue: yamlRouting?.taskQueue,
        });
        if (args.assigned_to) {
            await escalationService.claimEscalation(escalation.id, args.assigned_to, 240);
        }
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        type: 'waitFor',
                        signalId,
                        escalationId: escalation.id,
                    }),
                }],
        };
    });
    logger_1.loggerRegistry.info(`[lt-mcp:server] ${name} ready (5 tools registered)`);
    return server;
}
/** Get the current MCP server instance. */
function getServer() {
    return server;
}
/** Stop the MCP server and release resources. */
async function stopServer() {
    if (server) {
        await server.close();
        server = null;
        logger_1.loggerRegistry.info('[lt-mcp:server] stopped');
    }
}
