import { expect, tap } from '@git.zone/tstest/tapbundle';
import { FritzboxCallmonitorClient, FritzboxCallmonitorIntegration, type IFritzboxCallmonitorConfig } from '../../ts/integrations/fritzbox_callmonitor/index.js';

const config: IFritzboxCallmonitorConfig = {
  phonebookName: 'Phone',
  prefixes: ['+49'],
  contacts: [{ name: 'Alice', numbers: ['+4930123456'], vip: true }],
};

tap.test('models manual call monitor events and does not fake live monitoring without a source', async () => {
  const runtime = await new FritzboxCallmonitorIntegration().setup(config, {});
  const processed = await runtime.callService!({
    domain: 'fritzbox_callmonitor',
    service: 'process_event',
    target: {},
    data: { line: '01.01.26 12:00:00;RING;0;030123456;+4930999;SIP0;' },
  });
  const snapshotResult = await runtime.callService!({ domain: 'fritzbox_callmonitor', service: 'snapshot', target: {} });
  const start = await runtime.callService!({ domain: 'fritzbox_callmonitor', service: 'start_monitor', target: {} });
  const snapshot = snapshotResult.data as Awaited<ReturnType<FritzboxCallmonitorClient['getSnapshot']>>;

  expect(processed.success).toBeTrue();
  expect(snapshot.call.state).toEqual('ringing');
  expect(snapshot.call.attributes.from_name).toEqual('Alice');
  expect(start.success).toBeFalse();
  expect(start.error || '').toInclude('require config.host');
  await runtime.destroy();
});

tap.test('subscribes through an injected event source and emits state changes', async () => {
  let unsubscribed = false;
  const events: unknown[] = [];
  const runtime = await new FritzboxCallmonitorIntegration().setup({
    ...config,
    eventSource: {
      subscribe: (handlerArg) => {
        handlerArg('01.01.26 12:00:00;RING;0;030123456;+4930999;SIP0;');
        return () => {
          unsubscribed = true;
        };
      },
    },
  }, {});

  const unsubscribe = await runtime.subscribe!((eventArg) => events.push(eventArg));
  await new Promise((resolve) => setTimeout(resolve, 0));
  const snapshot = (await runtime.callService!({ domain: 'fritzbox_callmonitor', service: 'snapshot', target: {} })).data as Awaited<ReturnType<FritzboxCallmonitorClient['getSnapshot']>>;
  await unsubscribe();

  expect(snapshot.connected).toBeTrue();
  expect(snapshot.call.state).toEqual('ringing');
  expect(events.some((eventArg) => typeof eventArg === 'object' && eventArg !== null && (eventArg as { type?: string }).type === 'state_changed')).toBeTrue();
  expect(unsubscribed).toBeTrue();
});

export default tap.start();
