import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DoorbirdIntegration, DoorbirdMapper, type IDoorbirdCommandRequest, type IDoorbirdInfo } from '../../ts/integrations/doorbird/index.js';

const rawInfo: IDoorbirdInfo = {
  FIRMWARE: '000122',
  BUILD_NUMBER: '42',
  'DEVICE-TYPE': 'D1101V',
  PRIMARY_MAC_ADDR: '1CCAE3AABBCC',
  WIFI_MAC_ADDR: '1CCAE3DDEEFF',
  RELAYS: ['1', '2'],
};

tap.test('maps DoorBird snapshots to cameras, status, relay/light buttons, and events', async () => {
  const snapshot = DoorbirdMapper.toSnapshot({
    config: { host: 'doorbird.local', username: 'user', password: 'pass', name: 'Front Door' },
    rawData: { info: rawInfo, status: { doorbell: true, motion: false } },
    online: true,
    source: 'manual',
  });
  const devices = DoorbirdMapper.toDevices(snapshot);
  const entities = DoorbirdMapper.toEntities(snapshot);

  expect(snapshot.deviceInfo.macAddress).toEqual('1ccae3aabbcc');
  expect(snapshot.deviceInfo.relays).toEqual(['1', '2']);
  expect(snapshot.deviceInfo.swVersion).toEqual('000122 42');
  expect(snapshot.cameras.find((cameraArg) => cameraArg.id === 'live')?.stillImageUrl).toContain('user:pass@doorbird.local');
  expect(devices[0].id).toEqual('doorbird.device.1ccae3aabbcc');
  expect(entities.find((entityArg) => entityArg.attributes?.key === 'doorbell')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.attributes?.key === 'motion')?.state).toEqual('off');
  expect(entities.filter((entityArg) => String(entityArg.platform) === 'camera').length).toEqual(3);
  expect(entities.find((entityArg) => entityArg.attributes?.relay === '2')?.available).toBeTrue();
  expect(entities.find((entityArg) => entityArg.attributes?.action === 'turn_light_on')?.available).toBeTrue();
  expect(entities.some((entityArg) => String(entityArg.platform) === 'event')).toBeTrue();
});

tap.test('maps button and domain services to DoorBird command shapes', async () => {
  const snapshot = DoorbirdMapper.toSnapshot({ config: { host: 'doorbird.local', name: 'Front Door' }, rawData: { info: rawInfo }, online: true, source: 'manual' });
  const relay = DoorbirdMapper.commandForService(snapshot, { domain: 'button', service: 'press', target: { entityId: 'button.front_door_relay_2' } });
  const light = DoorbirdMapper.commandForService(snapshot, { domain: 'doorbird', service: 'turn_light_on', target: {} });
  const favorite = DoorbirdMapper.commandForService(snapshot, { domain: 'doorbird', service: 'change_favorite', target: {}, data: { type: 'http', title: 'Home Assistant (front_door_doorbell)', value: 'http://ha/api/doorbird/front?token=abc' } });

  expect(relay?.action).toEqual('energize_relay');
  expect(relay?.relay).toEqual('2');
  expect(light?.action).toEqual('turn_light_on');
  expect(favorite?.action).toEqual('change_favorite');
  expect(favorite?.favorite?.type).toEqual('http');
});

tap.test('does not report live command success without HTTP transport or executor', async () => {
  const snapshot = DoorbirdMapper.toSnapshot({ config: { name: 'Static DoorBird' }, rawData: { info: rawInfo }, online: true, source: 'manual' });
  const runtime = await new DoorbirdIntegration().setup({ snapshot }, {});
  const result = await runtime.callService?.({ domain: 'doorbird', service: 'energize_relay', target: {}, data: { relay: '1' } });

  expect(result?.success).toBeFalse();
  expect(result?.error).toContain('config.host');
  await runtime.destroy();
});

tap.test('models relay/light commands through an injected executor', async () => {
  const commands: IDoorbirdCommandRequest[] = [];
  const snapshot = DoorbirdMapper.toSnapshot({ config: { name: 'Executor DoorBird' }, rawData: { info: rawInfo }, online: true, source: 'manual' });
  const runtime = await new DoorbirdIntegration().setup({
    snapshot,
    commandExecutor: {
      execute: async (requestArg) => {
        commands.push(requestArg);
        return { ok: true, accepted: requestArg.action };
      },
    },
  }, {});

  const result = await runtime.callService?.({ domain: 'doorbird', service: 'turn_light_on', target: {} });

  expect(result?.success).toBeTrue();
  expect(commands[0].action).toEqual('turn_light_on');
  await runtime.destroy();
});

export default tap.start();
