import { strict as assert } from 'node:assert';
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { describe, it } from 'node:test';

import { saveHiveCastHostLink } from '../../src/utils/hivecast-link-store.js';

describe('HiveCast link store', () => {
  it('keeps a normal linked Device on local NATS when the saved local-owner snapshot is missing', () => {
    const root = mkdtempSync(join(tmpdir(), 'mx-hivecast-link-store-'));
    try {
      const matrixHome = join(root, '.matrix');
      const hostConfigPath = join(matrixHome, 'host.json');
      mkdirSync(matrixHome, { recursive: true });
      writeFileSync(hostConfigPath, `${JSON.stringify({
        kind: 'MatrixHostConfig',
        version: 1,
        home: matrixHome,
        transport: {
          root: 'richard-santomauro-nimbletec-com',
          authorityRoot: 'richard-santomauro-nimbletec-com',
          addressRoot: 'richard-santomauro-nimbletec-com',
          nats: {
            mode: 'external',
            url: 'nats://local.hivecast.ai:4222',
            wsUrl: 'wss://local.hivecast.ai/nats-ws',
            credentialsRef: 'file:/var/lib/hivecast/credentials/hivecast-nats.json',
          },
        },
      }, null, 2)}\n`);

      saveHiveCastHostLink({
        cwd: root,
        matrixHome,
        cloudUrl: 'https://local.hivecast.ai',
        authorityRoot: 'richard-santomauro-nimbletec-com',
        deviceRegistryRoot: 'richard-santomauro-nimbletec-com',
        hostLinkId: 'hostlink_test',
        hostId: 'install_test',
        principalId: 'principal_test',
        hostName: 'test-device',
        deviceSlug: 'test-device',
        routeKey: 'richard-santomauro-nimbletec-com',
        publicNamespace: 'richard-santomauro-nimbletec-com',
        spaceId: 'space_test',
        authorityCoordinator: false,
        nats: {
          url: 'nats://local.hivecast.ai:4222',
          wsUrl: 'wss://local.hivecast.ai/nats-ws',
        },
        natsCredentials: {
          jwt: 'jwt',
          seed: 'seed',
        },
      });

      const hostConfig = JSON.parse(readFileSync(hostConfigPath, 'utf8')) as {
        readonly transport?: {
          readonly root?: string;
          readonly authorityRoot?: string;
          readonly nats?: {
            readonly url?: string;
            readonly wsUrl?: string;
            readonly credentialsRef?: string;
            readonly binaryPath?: string;
          };
        };
      };

      assert.equal(hostConfig.transport?.root, 'richard-santomauro-nimbletec-com');
      assert.equal(hostConfig.transport?.authorityRoot, 'richard-santomauro-nimbletec-com');
      assert.equal(hostConfig.transport?.nats?.url, 'nats://127.0.0.1:4222');
      assert.equal(hostConfig.transport?.nats?.wsUrl, 'ws://127.0.0.1:4223');
      assert.equal(hostConfig.transport?.nats?.credentialsRef, undefined);
      assert.equal(hostConfig.transport?.nats?.binaryPath, undefined);
      assert.equal(Object.prototype.hasOwnProperty.call(hostConfig, 'natsTopology'), false);
      assert.equal(existsSync(join(matrixHome, 'credentials', 'hivecast-nats.creds')), false);
    } finally {
      rmSync(root, { recursive: true, force: true });
    }
  });

  it('configures linked Device leaf-node transport when the platform exchange advertises it', () => {
    const root = mkdtempSync(join(tmpdir(), 'mx-hivecast-link-store-leaf-'));
    try {
      const matrixHome = join(root, '.matrix');
      const hostConfigPath = join(matrixHome, 'host.json');
      mkdirSync(matrixHome, { recursive: true });
      writeFileSync(hostConfigPath, `${JSON.stringify({
        kind: 'MatrixHostConfig',
        version: 1,
        home: matrixHome,
        transport: {
          root: 'local-install-test',
          authorityRoot: 'local-install-test',
          addressRoot: 'local-install-test',
          nats: {
            mode: 'external',
            url: 'nats://127.0.0.1:4222',
            wsUrl: 'ws://127.0.0.1:4223',
          },
        },
      }, null, 2)}\n`);

      saveHiveCastHostLink({
        cwd: root,
        matrixHome,
        cloudUrl: 'https://local.hivecast.ai',
        authorityRoot: 'richard-santomauro-nimbletec-com',
        deviceRegistryRoot: 'richard-santomauro-nimbletec-com',
        hostLinkId: 'hostlink_test',
        hostId: 'install_test',
        principalId: 'principal_test',
        hostName: 'test-device',
        deviceSlug: 'test-device',
        routeKey: 'richard-santomauro-nimbletec-com',
        publicNamespace: 'richard-santomauro-nimbletec-com',
        spaceId: 'space_test',
        authorityCoordinator: false,
        nats: {
          url: 'nats://local.hivecast.ai:4222',
          wsUrl: 'wss://local.hivecast.ai/nats-ws',
          leafnodeUrl: 'nats://local.hivecast.ai:7422',
        },
        natsCredentials: {
          jwt: 'jwt',
          seed: 'seed',
        },
      });

      const hostConfig = JSON.parse(readFileSync(hostConfigPath, 'utf8')) as {
        readonly transport?: {
          readonly root?: string;
          readonly authorityRoot?: string;
          readonly nats?: {
            readonly url?: string;
            readonly wsUrl?: string;
            readonly credentialsRef?: string;
            readonly binaryPath?: string;
          };
        };
        readonly natsTopology?: {
          readonly mode?: string;
          readonly clientUrl?: string;
          readonly wsUrl?: string;
          readonly leafnodes?: readonly {
            readonly url?: string;
            readonly credentialsRef?: string;
          }[];
        };
      };
      const link = JSON.parse(readFileSync(join(matrixHome, 'credentials', 'hivecast-link.json'), 'utf8')) as {
        readonly credentials?: {
          readonly natsLeafnodeCredentialRef?: string;
        };
      };
      const leafCredentials = readFileSync(join(matrixHome, 'credentials', 'hivecast-nats.creds'), 'utf8');

      assert.equal(hostConfig.transport?.root, 'richard-santomauro-nimbletec-com');
      assert.equal(hostConfig.transport?.authorityRoot, 'richard-santomauro-nimbletec-com');
      assert.equal(hostConfig.transport?.nats?.url, 'nats://127.0.0.1:4222');
      assert.equal(hostConfig.transport?.nats?.wsUrl, 'ws://127.0.0.1:4223');
      assert.equal(hostConfig.transport?.nats?.credentialsRef, undefined);
      assert.equal(hostConfig.transport?.nats?.binaryPath, undefined);
      assert.equal(hostConfig.natsTopology?.mode, 'leafnode');
      assert.equal(hostConfig.natsTopology?.clientUrl, 'nats://127.0.0.1:4222');
      assert.equal(hostConfig.natsTopology?.wsUrl, 'ws://127.0.0.1:4223');
      assert.equal(hostConfig.natsTopology?.leafnodes?.[0]?.url, 'nats://local.hivecast.ai:7422');
      assert.equal(hostConfig.natsTopology?.leafnodes?.[0]?.credentialsRef, 'file:credentials/hivecast-nats.creds');
      assert.equal(link.credentials?.natsLeafnodeCredentialRef, 'file:credentials/hivecast-nats.creds');
      assert.match(leafCredentials, /-----BEGIN NATS USER JWT-----\njwt\n------END NATS USER JWT------/);
      assert.match(leafCredentials, /-----BEGIN USER NKEY SEED-----\nseed\n------END USER NKEY SEED------/);
    } finally {
      rmSync(root, { recursive: true, force: true });
    }
  });
});
