import { createServer } from 'node:http';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { HunterDouglasPowerViewClient, HunterDouglasPowerViewIntegration } from '../../ts/integrations/hunterdouglas_powerview/index.js';

tap.test('reads PowerView legacy local HTTP snapshots and executes cover/scene commands', async () => {
  const requests: Array<{ url: string; method?: string; body: string }> = [];
  const server = createServer((requestArg, responseArg) => {
    const chunks: Buffer[] = [];
    requestArg.on('data', (chunkArg) => chunks.push(Buffer.isBuffer(chunkArg) ? chunkArg : Buffer.from(chunkArg)));
    requestArg.on('end', () => {
      const body = Buffer.concat(chunks).toString('utf8');
      requests.push({ url: requestArg.url || '', method: requestArg.method, body });
      responseArg.setHeader('content-type', 'application/json');
      const url = new URL(requestArg.url || '/', 'http://127.0.0.1');

      if (url.pathname === '/api/fwversion') {
        responseArg.end(JSON.stringify({ firmware: { mainProcessor: { revision: 2, subRevision: 1, build: 0, name: 'PV Hub2.0' } } }));
        return;
      }
      if (url.pathname === '/api/userdata') {
        responseArg.end(JSON.stringify({ userData: { hubName: Buffer.from('HTTP PowerView').toString('base64'), serialNumber: 'HTTP123', macAddress: '002674abcdef', ip: '127.0.0.1', firmware: { mainProcessor: { revision: 2, subRevision: 1, build: 0, name: 'PV Hub2.0' } } } }));
        return;
      }
      if (url.pathname === '/api/rooms') {
        responseArg.end(JSON.stringify({ roomData: [{ id: 1, name: Buffer.from('Office').toString('base64') }] }));
        return;
      }
      if (url.pathname === '/api/scenes') {
        if (url.searchParams.get('sceneId') === '10') {
          responseArg.end(JSON.stringify({ shadeIds: [20] }));
          return;
        }
        responseArg.end(JSON.stringify({ sceneData: [{ id: 10, roomId: 1, name: Buffer.from('Morning').toString('base64') }] }));
        return;
      }
      if (url.pathname === '/api/shades') {
        responseArg.end(JSON.stringify({ shadeData: [{ id: 20, roomId: 1, name: Buffer.from('Office Shade').toString('base64'), type: 1, capabilities: 0, batteryKind: 1, positions: { posKind1: 1, position1: 32768 } }] }));
        return;
      }
      if (url.pathname === '/api/shades/20' && requestArg.method === 'PUT') {
        responseArg.end(JSON.stringify({ ok: true }));
        return;
      }
      responseArg.statusCode = 404;
      responseArg.end(JSON.stringify({ error: 'not found' }));
    });
  });

  await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));
  try {
    const address = server.address();
    const port = typeof address === 'object' && address ? address.port : 0;
    const client = new HunterDouglasPowerViewClient({ host: '127.0.0.1', port, timeoutMs: 1000 });
    const snapshot = await client.getSnapshot();

    expect(snapshot.online).toBeTrue();
    expect(snapshot.source).toEqual('http');
    expect(snapshot.hub.id).toEqual('HTTP123');
    expect(snapshot.shades[0].positions.primary).toEqual(50);

    const runtime = await new HunterDouglasPowerViewIntegration().setup({ host: '127.0.0.1', port, timeoutMs: 1000 }, {});
    const cover = await runtime.callService!({ domain: 'cover', service: 'set_cover_position', target: { entityId: 'cover.office_shade' }, data: { position: 25 } });
    const scene = await runtime.callService!({ domain: 'scene', service: 'turn_on', target: { entityId: 'scene.morning' } });

    expect(cover.success).toBeTrue();
    expect(scene.success).toBeTrue();
    expect(requests.some((requestArg) => requestArg.url === '/api/userdata')).toBeTrue();
    expect(requests.some((requestArg) => requestArg.url === '/api/shades/20' && requestArg.method === 'PUT' && requestArg.body.includes('position1'))).toBeTrue();
    expect(requests.some((requestArg) => requestArg.url === '/api/scenes?sceneId=10')).toBeTrue();
    await runtime.destroy();
  } finally {
    await new Promise<void>((resolve, reject) => server.close((errorArg) => errorArg ? reject(errorArg) : resolve()));
  }
});

export default tap.start();
