import { expect, tap } from '@git.zone/tstest/tapbundle';
import { DenonIntegration, createDenonDiscoveryDescriptor, type IDenonSnapshot } from '../../ts/integrations/denon/index.js';

const snapshot: IDenonSnapshot = {
  receiverInfo: {
    name: 'Static Denon',
    manufacturer: 'Denon',
    modelName: 'DRA-N5',
    serialNumber: 'ABC12345',
  },
  state: {
    power: 'PWSTANDBY',
    state: 'off',
    volumeMax: 60,
    muted: true,
    source: 'CD',
    sourceName: 'CD',
    sourceList: ['CD', 'TV'],
  },
  sourceMap: { CD: 'CD', TV: 'TV' },
  online: true,
  available: true,
  source: 'manual',
};

tap.test('matches manual Denon entries and creates config flow output', async () => {
  const descriptor = createDenonDiscoveryDescriptor();
  const manualMatcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'denon-manual-match');
  const match = await manualMatcher!.matches({ name: 'Denon import', snapshot }, {});

  expect(match.matched).toBeTrue();
  expect(match.normalizedDeviceId).toEqual('ABC12345');
  expect(match.candidate?.integrationDomain).toEqual('denon');

  const validation = await descriptor.getValidators()[0].validate(match.candidate!, {});
  expect(validation.matched).toBeTrue();

  const done = await (await new DenonIntegration().configFlow.start(match.candidate!, {})).submit!({});
  expect(done.kind).toEqual('done');
  expect(done.config?.name).toEqual('Static Denon');
  expect(done.config?.port).toEqual(23);
  expect(done.config?.snapshot?.state.muted).toBeTrue();
});

tap.test('does not report command success for read-only static snapshots', async () => {
  const runtime = await new DenonIntegration().setup({ snapshot }, {});
  const result = await runtime.callService?.({ domain: 'media_player', service: 'turn_off', target: { entityId: 'media_player.static_denon' }, data: {} });

  expect(result?.success).toBeFalse();
  expect(result?.error).toContain('Static snapshots/manual data are read-only');
  await runtime.destroy();
});

tap.test('delegates Denon commands to an injected executor', async () => {
  const commands: unknown[] = [];
  const runtime = await new DenonIntegration().setup({
    snapshot,
    commandExecutor: {
      execute: async (requestArg) => {
        commands.push(requestArg);
        return [];
      },
    },
  }, {});

  const result = await runtime.callService?.({ domain: 'media_player', service: 'turn_on', target: {}, data: {} });

  expect(result?.success).toBeTrue();
  expect((commands[0] as { rawCommand?: string }).rawCommand).toEqual('PWON');
  await runtime.destroy();
});

export default tap.start();
