// src/engine/remoting/RemoteProxy.ts

import type { IMatrixContext } from '../core/IMatrixContext';
import { RequestReply } from './RequestReply';
import type { IInterfaceDescriptor, IMethodSpec } from '../reflection/IInterfaceDescriptor';

function opFor(methodName: string, spec?: IMethodSpec): string {
  return spec?.op ?? methodName;
}

/**
 * Dynamic proxy for a remote mount's interface.
 * All calls go through RequestReply.execute.
 */
export class RemoteProxy {
  static proxyMount<T extends object>(
    context: IMatrixContext,
    mount: string,
    iface?: IInterfaceDescriptor
  ): T {
    const methods = iface?.methods ?? {};

    return new Proxy({} as T, {
      get(_target, key: string | symbol) {
        if (typeof key !== 'string') return undefined;
        if (key === '__mount') return mount;
        if (key === '__context') return context;

        const spec: IMethodSpec | undefined = methods[key];
        const op = opFor(key, spec);

        return async (...args: unknown[]) => {
          const payload =
            args.length === 1 ? args[0] :
            args.length === 0 ? undefined :
            args;

          return RequestReply.execute<unknown, unknown>(context, mount, op, payload, {
            IMethodSpec: spec
          });
        };
      }
    }) as T;
  }
}

export const proxyMount = RemoteProxy.proxyMount;
