import { expect, tap } from '@git.zone/tstest/tapbundle';
import { BrotherConfigFlow, BrotherMapper, createBrotherDiscoveryDescriptor, type IBrotherSnapshot } from '../../ts/integrations/brother/index.js';

tap.test('matches Home Assistant Brother printer mDNS records', async () => {
  const descriptor = createBrotherDiscoveryDescriptor();
  const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'brother-mdns-match');
  const result = await matcher!.matches({
    type: '_printer._tcp.local.',
    name: 'Brother HL-L2350DW._printer._tcp.local.',
    host: 'brother-printer.local',
    port: 515,
    properties: {
      product: 'Brother HL-L2350DW',
      serial: 'BR123456',
      mac: 'AA:BB:CC:DD:EE:FF',
    },
  }, {});

  expect(result.matched).toBeTrue();
  expect(result.normalizedDeviceId).toEqual('BR123456');
  expect(result.candidate?.integrationDomain).toEqual('brother');
  expect(result.candidate?.host).toEqual('brother-printer.local');
  expect(result.candidate?.port).toEqual(161);
  expect(result.candidate?.model).toEqual('HL-L2350DW');
  expect(result.candidate?.metadata?.mdnsPort).toEqual(515);

  const validation = await descriptor.getValidators()[0].validate(result.candidate!, {});
  expect(validation.matched).toBeTrue();
  expect(validation.confidence).toEqual('certain');
});

tap.test('carries Brother discovery defaults into config flow entries', async () => {
  const descriptor = createBrotherDiscoveryDescriptor();
  const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'brother-mdns-match');
  const match = await matcher!.matches({
    type: '_printer._tcp.local.',
    name: 'Brother MFC-J995DW._printer._tcp.local.',
    host: '192.168.1.44',
    properties: { product: 'Brother MFC-J995DW' },
  }, {});
  const step = await new BrotherConfigFlow().start(match.candidate!, {});
  const done = await step.submit!({ host: '192.168.1.44', printerType: 'ink' });

  expect(done.kind).toEqual('done');
  expect(done.config?.host).toEqual('192.168.1.44');
  expect(done.config?.port).toEqual(161);
  expect(done.config?.community).toEqual('public');
  expect(done.config?.printerType).toEqual('ink');
  expect(done.config?.model).toEqual('MFC-J995DW');
});

tap.test('matches manual snapshot setup without requiring live SNMP transport', async () => {
  const snapshot: IBrotherSnapshot = BrotherMapper.toSnapshot({
    config: { name: 'Snapshot Brother', model: 'MFC-J995DW', serial: 'INK123', printerType: 'ink' },
    sensors: { status: 'ready', black_ink_remaining: 44 },
    online: true,
    source: 'manual',
  });
  const descriptor = createBrotherDiscoveryDescriptor();
  const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'brother-manual-match');
  const match = await matcher!.matches({ metadata: { snapshot } }, {});

  expect(match.matched).toBeTrue();
  expect(match.candidate?.host).toBeUndefined();
  expect(match.candidate?.metadata?.snapshot).toEqual(snapshot);

  const step = await new BrotherConfigFlow().start(match.candidate!, {});
  const done = await step.submit!({ printerType: 'ink' });
  expect(done.kind).toEqual('done');
  expect(done.config?.snapshot?.printer.serialNumber).toEqual('INK123');
  expect(done.config?.host).toBeUndefined();
});

tap.test('rejects Brother-looking candidates without any usable source', async () => {
  const validation = await createBrotherDiscoveryDescriptor().getValidators()[0].validate({
    source: 'manual',
    integrationDomain: 'brother',
    name: 'Brother without host',
  }, {});

  expect(validation.matched).toBeFalse();
  expect(validation.reason).toEqual('Brother candidate lacks host, snapshot, raw SNMP data, sensors, or client information.');
});

export default tap.start();
