import { expect, tap } from '@git.zone/tstest/tapbundle';
import { AgentDvrClient, AgentDvrIntegration, HomeAssistantAgentDvrIntegration } from '../../ts/integrations/agent_dvr/index.js';

tap.test('fetches live Agent DVR snapshots and transmits mapped local HTTP commands', async () => {
  const originalFetch = globalThis.fetch;
  const requests: string[] = [];
  globalThis.fetch = (async (inputArg: RequestInfo | URL) => {
    const url = typeof inputArg === 'string' ? inputArg : inputArg instanceof URL ? inputArg.toString() : inputArg.url;
    requests.push(url);
    const parsed = new URL(url);

    if (parsed.pathname.endsWith('/grab.jpg')) {
      return new Response(new Uint8Array([0xff, 0xd8, 0xff]), { headers: { 'content-type': 'image/jpeg' } });
    }

    const cmd = parsed.searchParams.get('cmd');
    if (cmd === 'getStatus') {
      return jsonResponse({ name: 'Agent Server', unique: 'agent-123', remoteAccess: false, version: '7.1.8.0', devices: 1, armed: true });
    }
    if (cmd === 'getObjects') {
      return jsonResponse({
        locations: [{ name: 'Porch' }],
        objectList: [{
          id: 2,
          typeID: 2,
          name: 'Porch Cam',
          locationIndex: 0,
          data: {
            recording: false,
            alerted: false,
            detected: true,
            online: true,
            alertsActive: true,
            detectorActive: true,
            connected: true,
            ptzid: -1,
            width: 1280,
            height: 720,
            mjpegStreamWidth: 640,
            mjpegStreamHeight: 360,
          },
        }],
      });
    }
    if (cmd === 'getProfiles') {
      return jsonResponse({ profiles: [{ name: 'home', active: false }, { name: 'away', active: true }, { name: 'night', active: false }] });
    }
    if (cmd === 'alertOff' || cmd === 'record' || cmd === 'arm' || cmd === 'setProfileByName') {
      return jsonResponse({ ok: true });
    }
    return jsonResponse({ ok: true });
  }) as typeof fetch;

  try {
    const client = new AgentDvrClient({ host: '192.168.1.90' });
    const snapshot = await client.getSnapshot();
    expect(snapshot.connected).toBeTrue();
    expect(snapshot.server.name).toEqual('Agent Server');
    expect(snapshot.server.activeProfile).toEqual('away');
    expect(snapshot.devices[0].urls.stillImageUrl).toEqual('http://192.168.1.90:8090/grab.jpg?oid=2&size=640x360');

    const image = await client.execute({ type: 'snapshot_image', service: 'snapshot', objectId: 2, objectTypeId: 2 });
    expect((image as { contentType: string }).contentType).toEqual('image/jpeg');

    const alert = await client.execute({
      type: 'camera_command',
      service: 'disable_alerts',
      objectId: 2,
      objectTypeId: 2,
      command: 'alertOff',
      httpCommands: [{ label: 'alertOff', path: 'command.cgi', params: { cmd: 'alertOff', oid: 2, ot: 2 }, expect: 'json' }],
    });
    expect((alert as { ok: boolean }).ok).toBeTrue();
    expect(requests.some((requestArg) => requestArg.includes('cmd=alertOff') && requestArg.includes('oid=2') && requestArg.includes('ot=2'))).toBeTrue();
  } finally {
    globalThis.fetch = originalFetch;
  }
});

tap.test('does not pretend Agent DVR commands succeeded without a live endpoint or executor', async () => {
  const client = new AgentDvrClient({});
  let missingEndpointError = '';
  try {
    await client.execute({
      type: 'camera_command',
      service: 'disable_alerts',
      objectId: 2,
      objectTypeId: 2,
      command: 'alertOff',
      httpCommands: [{ label: 'alertOff', path: 'command.cgi', params: { cmd: 'alertOff', oid: 2, ot: 2 }, expect: 'json' }],
    });
  } catch (errorArg) {
    missingEndpointError = errorArg instanceof Error ? errorArg.message : String(errorArg);
  }
  expect(missingEndpointError).toInclude('commands require config.host');
});

tap.test('sets up Agent DVR runtime and preserves the Home Assistant alias class', async () => {
  const integration = new AgentDvrIntegration();
  const alias = new HomeAssistantAgentDvrIntegration();
  expect(alias instanceof AgentDvrIntegration).toBeTrue();
  expect(integration.domain).toEqual('agent_dvr');

  const runtime = await integration.setup({
    connected: true,
    status: { name: 'Manual Agent', unique: 'manual-agent', armed: false, devices: 1 },
    devices: [{
      id: 2,
      typeID: 2,
      name: 'Manual Cam',
      data: { online: true, connected: true, alertsActive: false, detectorActive: true, recording: false, detected: false, alerted: false },
    }],
  }, {});
  const devices = await runtime.devices();
  const entities = await runtime.entities();
  expect(devices[0].integrationDomain).toEqual('agent_dvr');
  expect(entities.some((entityArg) => String(entityArg.platform) === 'camera')).toBeTrue();
  await runtime.destroy();
});

const jsonResponse = (valueArg: Record<string, unknown>): Response => {
  return new Response(JSON.stringify(valueArg), { headers: { 'content-type': 'application/json' } });
};

export default tap.start();
