"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = start;
const hotmesh_1 = require("@hotmeshio/hotmesh");
const logger_1 = require("../lib/logger");
const telemetry_1 = require("../lib/telemetry");
const events_1 = require("../lib/events");
const maintenance_1 = require("../services/maintenance");
const cron_1 = require("../services/cron");
const mcp_1 = require("../services/mcp");
const escalation_strategy_1 = require("../services/escalation-strategy");
const config_1 = require("./config");
const adapters_1 = require("./adapters");
const workers_1 = require("./workers");
const server_1 = require("./server");
const socketio_1 = require("../lib/events/socketio");
/**
 * Start Long Tail with a declarative configuration.
 *
 * Handles database connection, migrations, adapter registration,
 * worker startup, and the embedded API server. Returns a client
 * for starting workflows and a shutdown function.
 *
 * @example Standard worker
 * ```typescript
 * import { start } from '@hotmeshio/long-tail';
 * import * as myWorkflow from './workflows/my-workflow';
 *
 * const lt = await start({
 *   database: { host: 'localhost', port: 5432, user: 'postgres', password: 'password', database: 'mydb' },
 *   workers: [
 *     { taskQueue: 'my-queue', workflow: myWorkflow.myWorkflow },
 *   ],
 * });
 * ```
 *
 * @example Dashboard for a remote system
 *
 * Point at another system's Postgres database and register its workflows
 * by name with `readonly` connections. The dashboard discovers and displays
 * them, and invocations are picked up by the real workers in the other system.
 *
 * ```typescript
 * import { start } from '@hotmeshio/long-tail';
 *
 * const lt = await start({
 *   database: { connectionString: 'postgres://shared-db:5432/other-system' },
 *   workers: [
 *     { taskQueue: 'ingest', workflow: 'orderPipeline', connection: { readonly: true } },
 *     { taskQueue: 'ingest', workflow: 'invoiceReconciler', connection: { readonly: true } },
 *     { taskQueue: 'billing', workflow: 'paymentProcessor', connection: { readonly: true } },
 *   ],
 *   server: { port: 4000 },
 * });
 *
 * // Workflows appear in the dashboard UI — invoke, audit, and view executions
 * // without competing for work. The real workers handle execution.
 * ```
 */
async function start(startConfig) {
    // 1. Apply database config
    (0, config_1.applyDatabaseConfig)(startConfig.database);
    // 2. Apply server/auth config
    await (0, config_1.applyServerAuthConfig)(startConfig);
    // 3. Register adapters
    (0, adapters_1.registerAdapters)(startConfig);
    logger_1.loggerRegistry.info('[long-tail] starting...');
    // 4-5. Collect workers, run migrations, start workers, seed data
    const { workers, builtinMcpServerFactories } = await (0, workers_1.collectWorkers)(startConfig);
    const { adminUserId } = await (0, workers_1.startWorkers)(startConfig, workers, builtinMcpServerFactories);
    // 6. Start embedded server (if enabled)
    const serverEnabled = startConfig.server?.enabled !== false;
    let httpServer = null;
    if (serverEnabled) {
        httpServer = (0, server_1.startServer)();
        // Attach socket.io adapter to the HTTP server (if registered)
        const socketAdapter = events_1.eventRegistry.getAdapter(socketio_1.SocketIOEventAdapter);
        if (socketAdapter && httpServer) {
            socketAdapter.attachServer(httpServer);
            await socketAdapter.connect();
        }
    }
    // 7. Return instance
    const connection = (0, workers_1.buildConnection)();
    const client = new hotmesh_1.Durable.Client({ connection });
    const shutdown = async () => {
        logger_1.loggerRegistry.info('[long-tail] shutting down...');
        if (httpServer) {
            await new Promise((resolve) => httpServer.close(() => resolve()));
        }
        if (mcp_1.mcpRegistry.hasAdapter) {
            await mcp_1.mcpRegistry.disconnect();
        }
        if (cron_1.cronRegistry.hasActiveCrons) {
            await cron_1.cronRegistry.disconnect();
        }
        if (maintenance_1.maintenanceRegistry.hasConfig) {
            await maintenance_1.maintenanceRegistry.disconnect();
        }
        if (events_1.eventRegistry.hasAdapters) {
            await events_1.eventRegistry.disconnect();
        }
        if (telemetry_1.telemetryRegistry.hasAdapter) {
            await telemetry_1.telemetryRegistry.disconnect();
        }
        escalation_strategy_1.escalationStrategyRegistry.clear();
        await hotmesh_1.Durable.shutdown();
        logger_1.loggerRegistry.info('[long-tail] shutdown complete');
    };
    return { client, shutdown, adminUserId };
}
