import './setup.mjs';
import test from 'node:test';
import assert from 'node:assert/strict';
import { load } from './setup.mjs';

const {
  buildVmListPath,
  buildHostPayloadFromVm,
  filterSummaryVms,
  normalizeBaseUrl,
  normalizeVCenterVm,
  previewVCenterHosts,
  settingsFromVCenterConnection,
  vmMatchesFilter
} = await load('../services/vcenterService.js');

test('normalizeBaseUrl trims trailing slashes', () => {
  assert.equal(normalizeBaseUrl('https://vcenter.lab.local///'), 'https://vcenter.lab.local');
});

test('standalone VMware host connections use the Web Services profile', async () => {
  const settings = settingsFromVCenterConnection({
    id: 'vc_host',
    target_type: 'host',
    base_url: 'https://esxi01.lab.local/sdk',
    username: 'root',
    password: 'secret',
    enabled: 1,
    api_mode: 'api'
  });

  assert.equal(settings.targetType, 'host');
  assert.equal(settings.apiMode, 'web-services');
  assert.equal(settings.baseUrl, 'https://esxi01.lab.local/sdk');

  await assert.rejects(
    () => previewVCenterHosts({ connection: { ...settings, name: 'ESXi host' } }),
    /Standalone VMware host connections/
  );
});

test('normalizeVCenterVm maps guest identity and networking into a host candidate', () => {
  const candidate = normalizeVCenterVm(
    { vm: 'vm-42', name: 'ENG-ENT-APP01', power_state: 'POWERED_ON' },
    { host_name: 'eng-ent-app01.contoso.local', ip_address: '10.42.1.20', full_name: { default_message: 'Microsoft Windows Server 2022' } },
    [{ ip: { ip_addresses: [{ ip_address: 'fe80::1' }, { ip_address: '10.42.1.21' }] } }]
  );

  assert.equal(candidate.id, 'vm-42');
  assert.equal(candidate.name, 'ENG-ENT-APP01');
  assert.equal(candidate.fqdn, 'eng-ent-app01.contoso.local');
  assert.equal(candidate.address, 'eng-ent-app01.contoso.local');
  assert.deepEqual(candidate.ipAddresses, ['10.42.1.20', '10.42.1.21']);
  assert.equal(candidate.osFamily, 'windows');
  assert.equal(candidate.guestFullName, 'Microsoft Windows Server 2022');
});

test('normalizeVCenterVm marks unknown guest operating systems as other', () => {
  const candidate = normalizeVCenterVm(
    { vm: 'vm-unknown', name: 'MYSTERY-01', power_state: 'POWERED_ON' },
    null,
    []
  );

  assert.equal(candidate.osFamily, 'other');
});

test('vmMatchesFilter supports hostname contains and IP equals matching', () => {
  const candidate = { name: 'ENG-ENT-APP01', fqdn: 'app01.contoso.local', address: 'app01.contoso.local', ipAddress: '10.42.1.20', ipAddresses: ['10.42.1.20'] };

  assert.equal(vmMatchesFilter(candidate, { field: 'hostname', operator: 'contains', value: 'eng-ent' }), true);
  assert.equal(vmMatchesFilter(candidate, { field: 'hostname', operator: 'contains', value: 'contoso' }), true);
  assert.equal(vmMatchesFilter(candidate, { field: 'ip', operator: 'equals', value: '10.42.1.20' }), true);
  assert.equal(vmMatchesFilter(candidate, { field: 'fqdn', operator: 'startsWith', value: 'db' }), false);
});

test('vmMatchesFilter matches guest-only host names after enrichment', () => {
  const candidate = normalizeVCenterVm(
    { vm: 'vm-200', name: 'KSUS01PAPP01', power_state: 'POWERED_ON' },
    { host_name: 'MCS-WIN-APP01.ent.mitekindustries.com', ip_address: '10.42.5.44', family: 'WINDOWS' },
    []
  );

  assert.equal(vmMatchesFilter(candidate, { field: 'hostname', operator: 'contains', value: 'MCS' }), true);
  assert.equal(vmMatchesFilter(candidate, { field: 'name', operator: 'contains', value: 'MCS' }), false);
});

test('filterSummaryVms scans the full VM summary list for VM-name filters', () => {
  const vms = [
    ...Array.from({ length: 900 }, (_, index) => ({ vm: `vm-${index}`, name: `ZZZ-${index}` })),
    { vm: 'vm-901', name: 'MCS-WIN-APP01' }
  ];
  const result = filterSummaryVms(vms, { field: 'name', operator: 'contains', value: 'MCS' });

  assert.equal(result.summaryFilterApplied, true);
  assert.equal(result.summaryMatched, 1);
  assert.equal(result.vms.length, 1);
  assert.equal(result.vms[0].name, 'MCS-WIN-APP01');
});

test('filterSummaryVms prefilters hostname searches by VM name and falls back when needed', () => {
  const vms = [{ vm: 'vm-1', name: 'MCS-WIN-APP01' }, { vm: 'vm-2', name: 'SQL-01' }];
  const matched = filterSummaryVms(vms, { field: 'hostname', operator: 'contains', value: 'MCS' });
  const fallback = filterSummaryVms(vms, { field: 'hostname', operator: 'contains', value: 'guest-only-name' });

  assert.equal(matched.summaryMatched, 1);
  assert.equal(matched.summaryFilterFallback, false);
  assert.deepEqual(matched.vms.map((vm) => vm.vm), ['vm-1', 'vm-2']);
  assert.equal(fallback.summaryMatched, 0);
  assert.equal(fallback.summaryFilterFallback, true);
  assert.equal(fallback.vms.length, 2);
});

test('buildVmListPath uses documented exact-name filters for api and rest profiles', () => {
  const filter = { field: 'name', operator: 'equals', value: 'MCS-WIN-APP01' };

  assert.equal(
    buildVmListPath({ vmListPath: '/api/vcenter/vm', vmNameParam: 'names' }, filter),
    '/api/vcenter/vm?names=MCS-WIN-APP01'
  );
  assert.equal(
    buildVmListPath({ vmListPath: '/rest/vcenter/vm', vmNameParam: 'filter.names' }, filter),
    '/rest/vcenter/vm?filter.names=MCS-WIN-APP01'
  );
  assert.equal(
    buildVmListPath({ vmListPath: '/api/vcenter/vm', vmNameParam: 'names' }, { field: 'name', operator: 'contains', value: 'MCS' }),
    '/api/vcenter/vm'
  );
});

test('buildHostPayloadFromVm attaches credential, tags, transport, and import notes', () => {
  const payload = buildHostPayloadFromVm(
    {
      id: 'vm-42',
      name: 'ENG-ENT-APP01',
      fqdn: 'eng-ent-app01.contoso.local',
      address: 'eng-ent-app01.contoso.local',
      osFamily: 'windows',
      powerState: 'POWERED_ON',
      guestFullName: 'Microsoft Windows Server 2022',
      ipAddresses: ['10.42.1.20']
    },
    { credentialId: 'cred_1', connectionId: 'vc_1', transport: 'winrm', tags: ['engineering'], visibility: 'group', groupId: 'grp_1' }
  );

  assert.equal(payload.credentialId, 'cred_1');
  assert.equal(payload.transport, 'winrm');
  assert.equal(payload.visibility, 'group');
  assert.equal(payload.groupId, 'grp_1');
  assert.equal(payload.sourceType, 'vmware');
  assert.equal(payload.sourceConnectionId, 'vc_1');
  assert.equal(payload.sourceRef, 'vm-42');
  assert.ok(payload.tags.includes('vcenter:vm-42'));
  assert.ok(payload.tags.includes('engineering'));
  assert.match(payload.notes, /Imported from VMware vCenter VM vm-42/);
});
