import { expect, tap } from '@git.zone/tstest/tapbundle';
import { AmcrestMapper, type IAmcrestSnapshot } from '../../ts/integrations/amcrest/index.js';

const snapshot: IAmcrestSnapshot = {
  deviceInfo: {
    id: 'AMC123',
    name: 'Front Door Amcrest',
    manufacturer: 'Amcrest',
    model: 'IP2M-841',
    serialNumber: 'AMC123',
    host: '192.168.1.30',
    port: 80,
    protocol: 'http',
    online: true,
  },
  cameras: [{
    id: '0',
    name: 'Front Door Camera',
    channel: 0,
    resolution: 'high',
    subtype: 0,
    streamSource: 'rtsp',
    snapshotUrl: 'http://192.168.1.30:80/cgi-bin/snapshot.cgi?channel=0',
    mjpegUrl: 'http://192.168.1.30:80/cgi-bin/mjpg/video.cgi?channel=0&subtype=0',
    rtspUrl: 'rtsp://user:pass@192.168.1.30:554/cam/realmonitor?channel=1&subtype=0',
    isStreaming: true,
    isRecording: false,
    motionDetectionEnabled: true,
    audioEnabled: true,
    supportsPtz: true,
    available: true,
  }],
  sensors: [{ key: 'ptz_preset', name: 'PTZ Preset', value: 2, entityCategory: 'diagnostic', available: true }],
  binarySensors: [
    { key: 'online', name: 'Online', isOn: true, deviceClass: 'connectivity', shouldPoll: true, available: true },
    { key: 'motion_detected', name: 'Motion Detected', isOn: true, deviceClass: 'motion', eventCodes: ['VideoMotion'], available: true },
  ],
  switches: [{ key: 'privacy_mode', name: 'Privacy Mode', isOn: false, command: 'privacy_mode', entityCategory: 'config', available: true }],
  events: [],
  currentSettings: { privacy_mode: false },
  connected: true,
  updatedAt: '2026-01-01T00:00:00.000Z',
};

tap.test('maps Amcrest camera streams, binary sensors, sensors, and switches', async () => {
  const devices = AmcrestMapper.toDevices(snapshot);
  const entities = AmcrestMapper.toEntities(snapshot);

  expect(devices.length).toEqual(1);
  expect(devices[0].features.some((featureArg) => featureArg.capability === 'camera')).toBeTrue();
  expect(entities.find((entityArg) => entityArg.id === 'camera.front_door_camera')?.attributes?.rtspUrl).toEqual('rtsp://user:pass@192.168.1.30:554/cam/realmonitor?channel=1&subtype=0');
  expect(entities.find((entityArg) => entityArg.id === 'binary_sensor.motion_detected')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'sensor.ptz_preset')?.state).toEqual(2);
  expect(entities.find((entityArg) => entityArg.id === 'switch.privacy_mode')?.state).toEqual('off');
});

tap.test('models camera, switch, snapshot, and PTZ services as explicit commands', async () => {
  const streamCommand = AmcrestMapper.commandForService(snapshot, {
    domain: 'camera',
    service: 'stream_source',
    target: { entityId: 'camera.front_door_camera' },
  });
  const snapshotCommand = AmcrestMapper.commandForService(snapshot, {
    domain: 'camera',
    service: 'snapshot',
    target: { entityId: 'camera.front_door_camera' },
  });
  const privacyCommand = AmcrestMapper.commandForService(snapshot, {
    domain: 'switch',
    service: 'turn_on',
    target: { entityId: 'switch.privacy_mode' },
  });
  const ptzCommand = AmcrestMapper.commandForService(snapshot, {
    domain: 'amcrest',
    service: 'ptz_control',
    target: { entityId: 'camera.front_door_camera' },
    data: { movement: 'left', travel_time: '0.1' },
  });
  const presetCommand = AmcrestMapper.commandForService(snapshot, {
    domain: 'amcrest',
    service: 'goto_preset',
    target: { entityId: 'camera.front_door_camera' },
    data: { preset: 2 },
  });

  expect(streamCommand?.type).toEqual('stream_source');
  expect(snapshotCommand?.type).toEqual('snapshot_image');
  expect(snapshotCommand?.httpCommands?.[0].path).toEqual('/cgi-bin/snapshot.cgi?channel=0');
  expect(privacyCommand?.type).toEqual('set_privacy_mode');
  expect(privacyCommand?.enabled).toBeTrue();
  expect(privacyCommand?.httpCommands?.[0].path.includes('LeLensMask[0].Enable=true')).toBeTrue();
  expect(ptzCommand?.type).toEqual('ptz_control');
  expect(ptzCommand?.movement).toEqual('left');
  expect(ptzCommand?.travelTime).toEqual(0.1);
  expect(presetCommand?.type).toEqual('goto_preset');
  expect(presetCommand?.httpCommands?.[0].path.includes('code=GotoPreset')).toBeTrue();
});

export default tap.start();
