import { buildContractInput, invokeContractRoute, openContractRouteStream, requireContractRoute, } from '../transport-http/index.js';
function splitArgs(args) {
    return args;
}
function requireMethod(contract, methodId) {
    return requireContractRoute(contract.operator.methods, methodId, 'operator method');
}
function requireMethodRoute(contract, methodId) {
    const method = requireMethod(contract, methodId);
    if (!method.http) {
        throw new Error(`Operator method "${methodId}" does not expose an HTTP binding`);
    }
    return method.http;
}
export function createOperatorRemoteClient(transport, contract) {
    function invokeTyped(methodId, input, options = {}) {
        return invokeContractRoute(transport, requireMethodRoute(contract, methodId), input, options);
    }
    function streamTyped(methodId, ...args) {
        const [input, options] = splitArgs(args);
        return openContractRouteStream(transport, requireMethodRoute(contract, methodId), input, options ?? { handlers: {} });
    }
    const client = {
        transport,
        contract,
        listMethods() {
            return contract.operator.methods;
        },
        getMethod(methodId) {
            return requireMethod(contract, methodId);
        },
        invoke: invokeTyped,
        stream: streamTyped,
        sessions: {
            create: (...args) => invokeTyped('sessions.create', ...args),
            get: (sessionId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('sessions.get', buildContractInput('sessionId', sessionId, input), options);
            },
            list: (...args) => invokeTyped('sessions.list', ...args),
            messages: {
                create: (sessionId, ...args) => {
                    const [input, options] = splitArgs(args);
                    return invokeTyped('sessions.messages.create', buildContractInput('sessionId', sessionId, input), options);
                },
                list: (sessionId, ...args) => {
                    const [input, options] = splitArgs(args);
                    return invokeTyped('sessions.messages.list', buildContractInput('sessionId', sessionId, input), options);
                },
            },
            inputs: {
                cancel: (sessionId, inputId, ...args) => {
                    const [input, options] = splitArgs(args);
                    return invokeTyped('sessions.inputs.cancel', {
                        sessionId,
                        inputId,
                        ...(input ?? {}),
                    }, options);
                },
            },
            followUp: (...args) => invokeTyped('sessions.followUp', ...args),
            steer: (...args) => invokeTyped('sessions.steer', ...args),
            close: (sessionId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('sessions.close', {
                    sessionId,
                    ...(input ?? {}),
                }, options);
            },
            reopen: (sessionId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('sessions.reopen', {
                    sessionId,
                    ...(input ?? {}),
                }, options);
            },
        },
        tasks: {
            create: (...args) => invokeTyped('tasks.create', ...args),
            get: (taskId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('tasks.get', {
                    taskId,
                    ...(input ?? {}),
                }, options);
            },
            list: (...args) => invokeTyped('tasks.list', ...args),
            status: (...args) => invokeTyped('tasks.status', ...args),
            cancel: (taskId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('tasks.cancel', {
                    taskId,
                    ...(input ?? {}),
                }, options);
            },
            retry: (taskId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('tasks.retry', {
                    taskId,
                    ...(input ?? {}),
                }, options);
            },
        },
        approvals: {
            list: (...args) => invokeTyped('approvals.list', ...args),
            claim: (approvalId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('approvals.claim', buildContractInput('approvalId', approvalId, input), options);
            },
            approve: (approvalId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('approvals.approve', buildContractInput('approvalId', approvalId, input), options);
            },
            deny: (approvalId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('approvals.deny', buildContractInput('approvalId', approvalId, input), options);
            },
            cancel: (approvalId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('approvals.cancel', buildContractInput('approvalId', approvalId, input), options);
            },
        },
        providers: {
            list: (...args) => invokeTyped('providers.list', ...args),
            get: (providerId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('providers.get', {
                    providerId,
                    ...(input ?? {}),
                }, options);
            },
            usage: (providerId, ...args) => {
                const [input, options] = splitArgs(args);
                return invokeTyped('providers.usage.get', {
                    providerId,
                    ...(input ?? {}),
                }, options);
            },
        },
        accounts: {
            snapshot: (...args) => invokeTyped('accounts.snapshot', ...args),
        },
        localAuth: {
            status: (...args) => invokeTyped('local_auth.status', ...args),
        },
        control: {
            snapshot: (...args) => invokeTyped('control.snapshot', ...args),
            status: (...args) => invokeTyped('control.status', ...args),
            contract: (...args) => invokeTyped('control.contract', ...args),
            methods: {
                list: (...args) => invokeTyped('control.methods.list', ...args),
                get: (methodId, ...args) => {
                    const [input, options] = splitArgs(args);
                    return invokeTyped('control.methods.get', {
                        methodId,
                        ...(input ?? {}),
                    }, options);
                },
            },
            auth: {
                current: (...args) => invokeTyped('control.auth.current', ...args),
                login: (...args) => invokeTyped('control.auth.login', ...args),
            },
            events: {
                catalog: (...args) => invokeTyped('control.events.catalog', ...args),
                stream: (...args) => streamTyped('control.events.stream', ...args),
            },
        },
        telemetry: {
            snapshot: (...args) => invokeTyped('telemetry.snapshot', ...args),
            events: (...args) => invokeTyped('telemetry.events.list', ...args),
            errors: (...args) => invokeTyped('telemetry.errors.list', ...args),
            traces: (...args) => invokeTyped('telemetry.traces.list', ...args),
            metrics: (...args) => invokeTyped('telemetry.metrics.get', ...args),
            otlp: {
                traces: (...args) => invokeTyped('telemetry.otlp.traces', ...args),
                logs: (...args) => invokeTyped('telemetry.otlp.logs', ...args),
                metrics: (...args) => invokeTyped('telemetry.otlp.metrics', ...args),
            },
            stream: (...args) => streamTyped('telemetry.stream', ...args),
        },
    };
    return client;
}
