import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DirectvClient, DirectvIntegration } from '../../ts/integrations/directv/index.js';

tap.test('refreshes a DirecTV snapshot from the local HTTP API', async () => {
  const originalFetch = globalThis.fetch;
  const requests: string[] = [];
  globalThis.fetch = (async (inputArg: RequestInfo | URL) => {
    const url = new URL(String(inputArg));
    requests.push(`${url.pathname}${url.search}`);
    if (url.pathname.endsWith('/info/getVersion')) {
      return new Response(JSON.stringify({ receiverId: ' RID 001 ', stbSoftwareVersion: '0x1234' }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    if (url.pathname.endsWith('/info/getLocations')) {
      return new Response(JSON.stringify({ locations: [{ clientAddr: '0', locationName: 'living room' }, { clientAddr: '1', locationName: 'bedroom' }] }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    if (url.pathname.endsWith('/info/mode') && url.searchParams.get('clientAddr') === '0') {
      return new Response(JSON.stringify({ mode: 0 }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    if (url.pathname.endsWith('/info/mode') && url.searchParams.get('clientAddr') === '1') {
      return new Response(JSON.stringify({ mode: 1 }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    if (url.pathname.endsWith('/tv/getTuned')) {
      return new Response(JSON.stringify({
        major: 202,
        minor: 65535,
        callsign: 'CNN',
        programId: 42,
        duration: 1800,
        title: 'News Hour',
        episodeTitle: 'Morning',
        offset: 120,
        rating: 'TV-G',
        startTime: 1767225600,
        isRecording: true,
      }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    if (url.pathname.endsWith('/remote/processKey') || url.pathname.endsWith('/tv/tune')) {
      return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    return new Response('not found', { status: 404 });
  }) as typeof globalThis.fetch;

  try {
    const client = new DirectvClient({ host: '192.168.1.55', timeoutMs: 5000 });
    const snapshot = await client.refresh();
    expect(snapshot.online).toBeTrue();
    expect(snapshot.source).toEqual('http');
    expect(snapshot.device.receiverId).toEqual('RID001');
    expect(snapshot.locations.length).toEqual(2);
    expect(snapshot.states[0].status).toEqual('active');
    expect(snapshot.states[0].program?.channel).toEqual('202');
    expect(snapshot.states[0].program?.programType).toEqual('tvshow');
    expect(snapshot.states[1].status).toEqual('standby');

    await client.sendRemoteKey('play', '0');
    await client.tune('10-2', '0');
    expect(requests.some((requestArg) => requestArg === '/remote/processKey?key=play&hold=keyPress&clientAddr=0')).toBeTrue();
    expect(requests.some((requestArg) => requestArg === '/tv/tune?major=10&minor=2&clientAddr=0')).toBeTrue();
  } finally {
    globalThis.fetch = originalFetch;
  }
});

tap.test('does not report live DirecTV success without host, snapshot, client, or executor', async () => {
  const runtime = await new DirectvIntegration().setup({}, {});
  const result = await runtime.callService!({ domain: 'directv', service: 'refresh', target: {} });
  expect(result.success).toBeFalse();
  const snapshot = result.data as { online: boolean; source: string; error?: string };
  expect(snapshot.online).toBeFalse();
  expect(snapshot.source).toEqual('runtime');
  expect(snapshot.error).toContain('requires a host');
  await runtime.destroy();
});

tap.test('uses a command executor for remote runtime commands', async () => {
  const commands: string[] = [];
  const runtime = await new DirectvIntegration().setup({
    receiverId: 'EXEC123',
    commandExecutor: {
      execute: async (requestArg) => {
        commands.push(`${requestArg.endpoint}?${new URL(requestArg.url).searchParams.toString()}`);
        return { ok: true };
      },
    },
  }, {});

  const result = await runtime.callService!({ domain: 'remote', service: 'send_command', target: {}, data: { command: ['play', 'pause'], num_repeats: 2, clientAddr: '0' } });
  expect(result.success).toBeTrue();
  expect(commands).toEqual([
    'remote/processKey?key=play&hold=keyPress&clientAddr=0',
    'remote/processKey?key=pause&hold=keyPress&clientAddr=0',
    'remote/processKey?key=play&hold=keyPress&clientAddr=0',
    'remote/processKey?key=pause&hold=keyPress&clientAddr=0',
  ]);
  await runtime.destroy();
});

export default tap.start();
