import { buildBuiltinAccount, resolveBuiltinAccount } from './builtin/accounts.js';
import { buildBuiltinContractHooks, editBuiltinAllowlist, getBuiltinDoctorReport, getBuiltinLifecycleState, listBuiltinRepairActions, resolveBuiltinAllowlist, } from './builtin/contracts.js';
import { listBuiltinCapabilities, listBuiltinOperatorActions, listBuiltinTools, } from './builtin/descriptors.js';
import { runHomeAssistantOperatorAction } from './builtin/homeassistant.js';
import { getBuiltinSetupSchema } from './builtin/setup-schema.js';
import { registerBuiltinChannelPlugins } from './builtin/plugins.js';
import { authorizeBuiltinActorAction, runBuiltinAccountAction, runBuiltinProviderApi, } from './builtin/account-actions.js';
import { readConversationKind, readDirectoryScope, readLifecycleAction, } from './builtin/parsing.js';
import { listBuiltinAgentTools, notifyBuiltinApprovalViaRouter, renderBuiltinChannelEvent, } from './builtin/rendering.js';
import { providerRuntimeStatus as providerRuntimeStatusForSurface } from './builtin/surfaces.js';
import { inferBuiltinTargetConversationKind, lookupBuiltinDirectory, parseBuiltinExplicitTarget, resolveBuiltinParentConversationCandidates, resolveBuiltinSessionTarget, resolveBuiltinTarget, } from './builtin/targets.js';
export class BuiltinChannelRuntime {
    deps;
    constructor(deps) {
        this.deps = deps;
    }
    registerPlugins() {
        registerBuiltinChannelPlugins({
            deps: this.deps,
            buildAccount: (surface) => this.buildAccount(surface),
            resolveAccount: (surface, accountId) => this.resolveAccount(surface, accountId),
            listCapabilities: (surface) => this.listCapabilities(surface),
            listTools: (surface) => this.listTools(surface),
            runTool: (surface, toolId, input) => this.runTool(surface, toolId, input),
            listOperatorActions: (surface) => this.listOperatorActions(surface),
            runOperatorAction: (surface, actionId, input) => this.runOperatorAction(surface, actionId, input),
            buildContractHooks: (surface) => this.buildContractHooks(surface),
            buildProductHooks: (surface) => this.buildProductHooks(surface),
            lookupDirectory: (surface, query, options) => this.lookupDirectory(surface, query, options),
            lookupRouteDirectory: (surface, query, options) => this.lookupRouteDirectory(surface, query, options),
            notifyApprovalViaRouter: (surface, approval, binding) => this.notifyApprovalViaRouter(surface, approval, binding),
            providerRuntimeStatus: (surface) => this.providerRuntimeStatus(surface),
        });
    }
    accountContext() {
        return {
            deps: this.deps,
            providerRuntimeStatus: (surface) => this.providerRuntimeStatus(surface),
        };
    }
    async buildAccount(surface) {
        return buildBuiltinAccount(this.accountContext(), surface);
    }
    async resolveAccount(surface, accountId) {
        return resolveBuiltinAccount(this.accountContext(), surface, accountId);
    }
    contractContext() {
        return {
            deps: this.deps,
            channelPolicy: this.deps.channelPolicy,
            buildAccount: (surface) => this.buildAccount(surface),
            resolveAccount: (surface, accountId) => this.resolveAccount(surface, accountId),
            resolveTarget: (surface, options) => this.resolveTarget(surface, options),
        };
    }
    async listCapabilities(surface) {
        const account = await this.buildAccount(surface);
        const plugin = this.deps.channelPlugins.getBySurface(surface);
        return listBuiltinCapabilities(surface, account, plugin?.capabilities ?? []);
    }
    listOperatorActions(surface) {
        return listBuiltinOperatorActions(surface);
    }
    listTools(surface) {
        return listBuiltinTools(surface);
    }
    async runTool(surface, toolId, input) {
        const tool = this.listTools(surface).find((entry) => entry.id === toolId || entry.name === toolId);
        if (!tool)
            return null;
        const actionId = tool.actionIds[0];
        if (!actionId)
            return null;
        return this.runOperatorAction(surface, actionId, input);
    }
    async runOperatorAction(surface, actionId, input) {
        if (surface === 'homeassistant') {
            const homeAssistantResult = await runHomeAssistantOperatorAction({ deps: this.deps }, actionId, input);
            if (homeAssistantResult.handled)
                return homeAssistantResult.result;
        }
        if (actionId === 'inspect-account') {
            const accountId = typeof input?.accountId === 'string' ? input.accountId : undefined;
            return accountId ? this.resolveAccount(surface, accountId) : this.buildAccount(surface);
        }
        if (actionId === 'inspect-status') {
            return this.deps.channelPlugins.listStatus().then((entries) => entries.find((entry) => entry.surface === surface) ?? null);
        }
        if (actionId === 'setup-schema') {
            return this.getSetupSchema(surface);
        }
        if (actionId === 'doctor') {
            const accountId = typeof input?.accountId === 'string' ? input.accountId : undefined;
            return this.getDoctorReport(surface, accountId);
        }
        if (actionId === 'repair-actions') {
            const accountId = typeof input?.accountId === 'string' ? input.accountId : undefined;
            return this.listRepairActions(surface, accountId);
        }
        if (actionId === 'lifecycle-state') {
            const accountId = typeof input?.accountId === 'string' ? input.accountId : undefined;
            return this.getLifecycleState(surface, accountId);
        }
        if (actionId === 'list-directory') {
            const scope = readDirectoryScope(input?.scope);
            return this.deps.channelPlugins.queryDirectory(surface, {
                query: typeof input?.query === 'string' ? input.query : undefined,
                ...(scope ? { scope } : {}),
                groupId: typeof input?.groupId === 'string' ? input.groupId : undefined,
                limit: typeof input?.limit === 'number' ? input.limit : undefined,
            });
        }
        if (actionId === 'list-capabilities') {
            return this.listCapabilities(surface);
        }
        if (actionId === 'account-action') {
            const action = readLifecycleAction(input?.action ?? input?.accountAction);
            if (!action) {
                return {
                    surface,
                    ok: false,
                    error: 'account-action requires a valid lifecycle action.',
                };
            }
            return this.runAccountAction(surface, action, typeof input?.accountId === 'string' ? input.accountId : undefined, input);
        }
        if (actionId === 'resolve-target') {
            const targetInput = typeof input?.target === 'string'
                ? input.target
                : typeof input?.input === 'string'
                    ? input.input
                    : typeof input?.query === 'string'
                        ? input.query
                        : '';
            if (targetInput.trim().length === 0) {
                return {
                    surface,
                    ok: false,
                    error: 'resolve-target requires "target" or "input".',
                };
            }
            const preferredKind = readConversationKind(input?.preferredKind);
            return this.resolveTarget(surface, {
                input: targetInput,
                ...(typeof input?.accountId === 'string' ? { accountId: input.accountId } : {}),
                ...(preferredKind ? { preferredKind } : {}),
                ...(typeof input?.threadId === 'string' ? { threadId: input.threadId } : {}),
                ...(typeof input?.createIfMissing === 'boolean' ? { createIfMissing: input.createIfMissing } : {}),
                ...(typeof input?.live === 'boolean' ? { live: input.live } : {}),
            });
        }
        if (actionId === 'authorize-actor-action') {
            const targetInput = typeof input?.target === 'string' ? input.target : undefined;
            const target = targetInput
                ? await this.resolveTarget(surface, {
                    input: targetInput,
                    ...(typeof input?.accountId === 'string' ? { accountId: input.accountId } : {}),
                    createIfMissing: true,
                })
                : undefined;
            return this.authorizeActorAction(surface, {
                actionId: typeof input?.actionId === 'string' ? input.actionId : 'unknown',
                ...(typeof input?.actorId === 'string' ? { actorId: input.actorId } : {}),
                ...(typeof input?.accountId === 'string' ? { accountId: input.accountId } : {}),
                ...(target ? { target } : {}),
                metadata: {},
            });
        }
        if (actionId === 'resolve-allowlist') {
            return this.resolveAllowlist(surface, {
                ...(Array.isArray(input?.add) ? { add: input.add.filter((entry) => typeof entry === 'string') } : {}),
                ...(Array.isArray(input?.remove) ? { remove: input.remove.filter((entry) => typeof entry === 'string') } : {}),
                ...(input?.kind === 'user' || input?.kind === 'channel' || input?.kind === 'group' ? { kind: input.kind } : {}),
            });
        }
        if (actionId === 'edit-allowlist') {
            return this.editAllowlist(surface, {
                ...(Array.isArray(input?.add) ? { add: input.add.filter((entry) => typeof entry === 'string') } : {}),
                ...(Array.isArray(input?.remove) ? { remove: input.remove.filter((entry) => typeof entry === 'string') } : {}),
                ...(typeof input?.groupId === 'string' ? { groupId: input.groupId } : {}),
                ...(typeof input?.channelId === 'string' ? { channelId: input.channelId } : {}),
                ...(typeof input?.workspaceId === 'string' ? { workspaceId: input.workspaceId } : {}),
                ...(input?.kind === 'user' || input?.kind === 'channel' || input?.kind === 'group' ? { kind: input.kind } : {}),
                ...(typeof input?.metadata === 'object' && input.metadata !== null ? { metadata: input.metadata } : {}),
            });
        }
        if (actionId === 'provider-api') {
            return this.runProviderApi(surface, input);
        }
        return null;
    }
    buildContractHooks(surface) {
        return buildBuiltinContractHooks(this.contractContext(), surface);
    }
    getSetupSchema(surface) {
        return getBuiltinSetupSchema(surface);
    }
    async listRepairActions(surface, accountId) {
        return listBuiltinRepairActions(this.contractContext(), surface, accountId);
    }
    async getDoctorReport(surface, accountId) {
        return getBuiltinDoctorReport(this.contractContext(), surface, accountId);
    }
    async getLifecycleState(surface, accountId) {
        return getBuiltinLifecycleState(this.contractContext(), surface, accountId);
    }
    async resolveAllowlist(surface, input) {
        return resolveBuiltinAllowlist(this.contractContext(), surface, input);
    }
    async editAllowlist(surface, input) {
        return editBuiltinAllowlist(this.contractContext(), surface, input);
    }
    buildProductHooks(surface) {
        return {
            runAccountAction: (action, accountId, input) => this.runAccountAction(surface, action, accountId, input),
            authorizeActorAction: (request) => this.authorizeActorAction(surface, request),
            parseExplicitTarget: (input, options) => this.parseExplicitTarget(surface, input, options),
            inferTargetConversationKind: (input, options) => this.inferTargetConversationKind(input, options),
            resolveTarget: (options) => this.resolveTarget(surface, options),
            resolveSessionTarget: (target) => this.resolveSessionTarget(target),
            resolveParentConversationCandidates: (options) => this.resolveParentConversationCandidates(surface, options),
            renderEvent: (request) => this.renderChannelEvent(surface, request),
            listAgentTools: () => this.listAgentTools(surface),
        };
    }
    async renderChannelEvent(surface, request) {
        return renderBuiltinChannelEvent({
            deps: this.deps,
            listTools: (currentSurface) => this.listTools(currentSurface),
            runTool: (currentSurface, toolId, input) => this.runTool(currentSurface, toolId, input),
        }, surface, request);
    }
    async notifyApprovalViaRouter(surface, approval, binding) {
        await notifyBuiltinApprovalViaRouter({
            deps: this.deps,
            listTools: (currentSurface) => this.listTools(currentSurface),
            runTool: (currentSurface, toolId, input) => this.runTool(currentSurface, toolId, input),
        }, surface, approval, binding);
    }
    listAgentTools(surface) {
        return listBuiltinAgentTools({
            deps: this.deps,
            listTools: (currentSurface) => this.listTools(currentSurface),
            runTool: (currentSurface, toolId, input) => this.runTool(currentSurface, toolId, input),
        }, surface);
    }
    async runAccountAction(surface, action, accountId, input) {
        return runBuiltinAccountAction({
            deps: this.deps,
            buildAccount: (currentSurface) => this.buildAccount(currentSurface),
            resolveAccount: (currentSurface, currentAccountId) => this.resolveAccount(currentSurface, currentAccountId),
        }, surface, action, accountId, input);
    }
    async authorizeActorAction(surface, request) {
        return authorizeBuiltinActorAction({
            deps: this.deps,
            buildAccount: (currentSurface) => this.buildAccount(currentSurface),
            resolveAccount: (currentSurface, currentAccountId) => this.resolveAccount(currentSurface, currentAccountId),
        }, surface, request);
    }
    async runProviderApi(surface, input) {
        return runBuiltinProviderApi({
            deps: this.deps,
            buildAccount: (currentSurface) => this.buildAccount(currentSurface),
            resolveAccount: (currentSurface, currentAccountId) => this.resolveAccount(currentSurface, currentAccountId),
        }, surface, input);
    }
    parseExplicitTarget(surface, input, options) {
        return parseBuiltinExplicitTarget(surface, input, options);
    }
    inferTargetConversationKind(input, options) {
        return inferBuiltinTargetConversationKind(input, options);
    }
    async resolveTarget(surface, options) {
        return resolveBuiltinTarget({ deps: this.deps }, surface, options);
    }
    async resolveParentConversationCandidates(surface, options) {
        return resolveBuiltinParentConversationCandidates({ deps: this.deps }, surface, options);
    }
    resolveSessionTarget(target) {
        return resolveBuiltinSessionTarget(target);
    }
    providerRuntimeStatus(surface) {
        return providerRuntimeStatusForSurface(this.deps, surface);
    }
    async lookupDirectory(surface, query, options) {
        return lookupBuiltinDirectory({ deps: this.deps }, surface, query, options);
    }
    async lookupRouteDirectory(surface, query, options) {
        return lookupBuiltinDirectory({ deps: this.deps }, surface, query, { ...options, live: false });
    }
}
