import { expect, tap } from '@git.zone/tstest/tapbundle';
import { FroniusConfigFlow, FroniusMapper, createFroniusDiscoveryDescriptor, type IFroniusRawData } from '../../ts/integrations/fronius/index.js';

const rawData: Partial<IFroniusRawData> = {
  loggerInfo: { Body: { Data: { UniqueID: 'LOGGER123', SWVersion: '1.2.3', ProductID: 'Datalogger Web' } } },
  inverterInfo: { Body: { Data: { '1': { DT: 1, PVPower: 5000, StatusCode: 7, UniqueID: 'INV123', CustomName: 'Roof Inverter' } } } },
  powerFlow: { Body: { Data: { Site: { P_PV: 4200, P_Load: -3000 } } } },
};

tap.test('matches Fronius DHCP leases by Home Assistant manifest MAC prefix', async () => {
  const descriptor = createFroniusDiscoveryDescriptor();
  const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'fronius-dhcp-match');
  const match = await matcher!.matches({ ip: '192.168.1.10', hostname: 'fronius-datalogger', macaddress: '00:03:AC:12:34:56' }, {});

  expect(match.matched).toBeTrue();
  expect(match.candidate?.integrationDomain).toEqual('fronius');
  expect(match.candidate?.host).toEqual('192.168.1.10');
  expect(match.candidate?.metadata?.dhcpMacPrefix).toEqual('0003AC*');
});

tap.test('matches manual Fronius snapshots and creates config flow output', async () => {
  const snapshot = FroniusMapper.toSnapshot({ config: { name: 'Snapshot SolarNet' }, rawData, online: true, source: 'manual' });
  const matcher = createFroniusDiscoveryDescriptor().getMatchers().find((matcherArg) => matcherArg.id === 'fronius-manual-match');
  const match = await matcher!.matches({ metadata: { snapshot } }, {});

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

  const done = await (await new FroniusConfigFlow().start(match.candidate!, {})).submit!({});
  expect(done.kind).toEqual('done');
  expect(done.config?.snapshot?.system.uniqueId).toEqual('LOGGER123');
  expect(done.config?.host).toBeUndefined();
});

tap.test('rejects Fronius-looking candidates without a usable local source', async () => {
  const validation = await createFroniusDiscoveryDescriptor().getValidators()[0].validate({
    source: 'manual',
    integrationDomain: 'fronius',
    name: 'Fronius without host',
  }, {});

  expect(validation.matched).toBeFalse();
  expect(validation.reason).toEqual('Fronius candidate lacks a host, injected client, snapshot, or raw data.');
});

export default tap.start();
