import { describe, it } from 'node:test';
import assert from 'node:assert/strict';

import { ActorServices } from '../ActorServices';
import { ScopedIntentResolver } from '../ScopedIntentResolver';
import type { IMatrixContext } from '../IMatrixContext';
import { ActorCallClient } from '../../remoting/ActorCallClient';
import type { RuntimeAddressContext } from '../../remoting/RuntimeAddressContext';
import { WELL_KNOWN_SERVICE_BINDINGS } from '../../../contracts/WellKnownServiceBindings';

const encoder = new TextEncoder();
const decoder = new TextDecoder();

interface CapturedRequest {
  readonly subject: string;
  readonly payload: Record<string, unknown>;
}

function createServicesHarness(): {
  readonly services: ActorServices;
  readonly requests: readonly CapturedRequest[];
} {
  return createServicesHarnessWithOptions({});
}

function createServicesHarnessWithOptions(options: {
  readonly omitNativeRequest?: boolean;
  readonly useFederationInvoke?: boolean;
  readonly transportRoot?: string;
}): {
  readonly services: ActorServices;
  readonly requests: readonly CapturedRequest[];
} {
  const requests: CapturedRequest[] = [];
  const subscriptions = new Map<string, (err: Error | null, msg: { readonly subject: string; readonly data: Uint8Array }) => void>();
  const transportRoot = options.transportRoot ?? 'test-user-1.WEB.SESSION-ABC';
  const context = {
    mount: 'web.dashboard',
    transport: {
      root: transportRoot,
      publish() {},
      subscribe() {
        return () => undefined;
      },
      getUnderlyingClient() {
        if (options.useFederationInvoke === true) {
          return {
            async invoke(targetRoot: string, toPath: string, body: unknown) {
              requests.push({
                subject: `${targetRoot}/${toPath}`,
                payload: body as Record<string, unknown>,
              });
              return {
                ok: true,
                targetRoot,
                toPath,
                payload: body,
              };
            },
          };
        }
        const client = {
          publish() {},
          subscribe(
            subject: string,
            options: { readonly callback: (err: Error | null, msg: { readonly subject: string; readonly data: Uint8Array }) => void },
          ) {
            subscriptions.set(subject, options.callback);
            return {
              unsubscribe() {
                subscriptions.delete(subject);
              },
            };
          },
          flush: async () => undefined,
        };
        if (options.omitNativeRequest === true) {
          return {
            ...client,
            publish(subject: string, data?: Uint8Array) {
              const payload = data && data.length > 0
                ? JSON.parse(decoder.decode(data)) as Record<string, unknown>
                : {};
              requests.push({ subject, payload });
              const replyTo = typeof payload.replyTo === 'string' ? payload.replyTo : null;
              if (!replyTo) return;
              const callback = subscriptions.get(replyTo);
              callback?.(null, {
                subject: replyTo,
                data: encoder.encode(JSON.stringify({
                  ok: true,
                  result: {
                    ok: true,
                    subject,
                    payload: payload.payload,
                  },
                  correlationId: payload.correlationId,
                })),
              });
            },
          };
        }
        return {
          ...client,
          async request(subject: string, data?: Uint8Array) {
            const payload = data && data.length > 0
              ? JSON.parse(decoder.decode(data)) as Record<string, unknown>
              : {};
            requests.push({ subject, payload });
            return {
              subject,
              data: encoder.encode(JSON.stringify({
                ok: true,
                result: {
                  ok: true,
                  subject,
                  payload: payload.payload,
                },
              })),
            };
          },
        };
      },
    },
    derive() {
      return context as IMatrixContext;
    },
    getService() {
      return undefined;
    },
    setService() {},
  } as unknown as IMatrixContext;
  const address: RuntimeAddressContext = {
    runtimeInstanceRoot: transportRoot,
    accountRoot: 'test-user-1',
    userSpaceRoot: 'test-user-1',
    platformRoot: 'SPACE-HIVECAST',
    isPlatformAdmin: false,
    principalId: 'principal:test-user-1',
    busToken: 'bus-token-user-1',
  };
  const call = new ActorCallClient(context, address);
  const resolver = new ScopedIntentResolver(call, WELL_KNOWN_SERVICE_BINDINGS);
  return {
    services: new ActorServices(resolver, address),
    requests,
  };
}

describe('ActorServices scoped intent facade', () => {
  it('routes account Device inventory through the account authority root', async () => {
    const harness = createServicesHarness();
    const response = await harness.services.user.devices.list();

    assert.deepEqual(response, {
      ok: true,
      subject: 'test-user-1.system.devices.$inbox',
      payload: {
        principalId: 'principal:test-user-1',
        busToken: 'bus-token-user-1',
        includeOffline: true,
      },
    });
    assert.equal(harness.requests[0]?.subject, 'test-user-1.system.devices.$inbox');
  });

  it('routes same-root account Device inventory through broker request replies', async () => {
    const harness = createServicesHarnessWithOptions({ transportRoot: 'test-user-1' });
    const response = await harness.services.user.devices.list();

    assert.deepEqual(response, {
      ok: true,
      subject: 'test-user-1.system.devices.$inbox',
      payload: {
        principalId: 'principal:test-user-1',
        busToken: 'bus-token-user-1',
        includeOffline: true,
      },
    });
    assert.equal(harness.requests[0]?.subject, 'test-user-1.system.devices.$inbox');
    assert.equal(Object.prototype.hasOwnProperty.call(harness.requests[0]?.payload ?? {}, 'replyTo'), false);
  });

  it('routes account Device inventory through platform auth', async () => {
    const harness = createServicesHarness();
    const response = await harness.services.platform.auth.accountDevices.list();

    assert.deepEqual(response, {
      ok: true,
      subject: 'SPACE-HIVECAST.system.auth.$inbox',
      payload: {
        principalId: 'principal:test-user-1',
        busToken: 'bus-token-user-1',
        includeGrants: true,
      },
    });
    assert.equal(harness.requests[0]?.subject, 'SPACE-HIVECAST.system.auth.$inbox');
  });

  it('routes platform auth through raw rooted subjects when browser NATS has no native request helper', async () => {
    const harness = createServicesHarnessWithOptions({ omitNativeRequest: true });
    const response = await harness.services.platform.auth.currentSession();

    assert.deepEqual(response, {
      ok: true,
      subject: 'SPACE-HIVECAST.system.auth.$inbox',
      payload: {},
    });
    assert.equal(harness.requests[0]?.subject, 'SPACE-HIVECAST.system.auth.$inbox');
  });

  it('routes platform auth through federation invoke when the browser transport is a federation peer', async () => {
    const harness = createServicesHarnessWithOptions({ useFederationInvoke: true });
    const response = await harness.services.platform.auth.currentSession();

    assert.deepEqual(response, {
      ok: true,
      targetRoot: 'SPACE-HIVECAST',
      toPath: 'system.auth.accepts.session.current',
      payload: {},
    });
    assert.equal(harness.requests[0]?.subject, 'SPACE-HIVECAST/system.auth.accepts.session.current');
  });

  it('routes platform capability checks through the platform service root', async () => {
    const harness = createServicesHarness();
    const response = await harness.services.platform.capabilities.check('devices.read');

    assert.deepEqual(response, {
      ok: true,
      subject: 'SPACE-HIVECAST.system.capabilities.$inbox',
      payload: {},
    });
    assert.equal(harness.requests[0]?.subject, 'SPACE-HIVECAST.system.capabilities.$inbox');
    assert.equal(harness.requests[0]?.payload.capability, 'devices.read');
  });

  it('routes direct user runtime introspection under the user authority root', async () => {
    const harness = createServicesHarness();
    const response = await harness.services.user.runtimes.introspectMount(
      'system.runtimes.RUNTIME-BROWSER-ABC',
    );

    assert.deepEqual(response, {
      ok: true,
      subject: 'test-user-1.system.runtimes.RUNTIME-BROWSER-ABC.$inbox',
      payload: {
        depth: 'full',
      },
    });
    assert.equal(harness.requests[0]?.subject, 'test-user-1.system.runtimes.RUNTIME-BROWSER-ABC.$inbox');
  });

  it('routes user runtime inventory with signed browser session scope', async () => {
    const harness = createServicesHarness();
    const response = await harness.services.user.runtimes.registered();

    assert.deepEqual(response, {
      ok: true,
      subject: 'test-user-1.system.runtimes.$inbox',
      payload: {
        namespaceRoot: 'test-user-1',
        authorityRoot: 'test-user-1',
        principalId: 'principal:test-user-1',
        busToken: 'bus-token-user-1',
        includeStale: true,
        includeOffline: true,
      },
    });
    assert.equal(harness.requests[0]?.subject, 'test-user-1.system.runtimes.$inbox');
  });

  it('routes same-root hosted runtime inventory through broker request replies', async () => {
    const harness = createServicesHarnessWithOptions({ transportRoot: 'test-user-1' });
    const response = await harness.services.user.runtimes.registered();

    assert.deepEqual(response, {
      ok: true,
      subject: 'test-user-1.system.runtimes.$inbox',
      payload: {
        namespaceRoot: 'test-user-1',
        authorityRoot: 'test-user-1',
        principalId: 'principal:test-user-1',
        busToken: 'bus-token-user-1',
        includeStale: true,
        includeOffline: true,
      },
    });
    assert.equal(harness.requests[0]?.subject, 'test-user-1.system.runtimes.$inbox');
    assert.equal(Object.prototype.hasOwnProperty.call(harness.requests[0]?.payload ?? {}, 'replyTo'), false);
  });

  it('routes explicit owned Space reads through that Space authority root', async () => {
    const harness = createServicesHarness();
    const response = await harness.services.space('richard-nimbletec').registry.query();

    assert.deepEqual(response, {
      ok: true,
      subject: 'richard-nimbletec.system.registry.$inbox',
      payload: {
        namespaceRoot: 'richard-nimbletec',
        authorityRoot: 'richard-nimbletec',
        includeStale: true,
      },
    });
    assert.equal(harness.requests[0]?.subject, 'richard-nimbletec.system.registry.$inbox');
  });
});
