import { expect, tap } from '@git.zone/tstest/tapbundle';
import { GoodweClient, GoodweIntegration, GoodweMapper, type IGoodweCommandRequest, type IGoodweRawData } from '../../ts/integrations/goodwe/index.js';

const rawData: Partial<IGoodweRawData> = {
  deviceInfo: { name: 'Runtime GoodWe', serialNumber: 'RUN123', model: 'GW5000-ES', modelFamily: 'ES' },
  runtimeData: { ppv: 1200, active_power: 900, battery_soc: 55 },
  settingsData: { grid_export_limit: 3000 },
  operationMode: 'general',
};

tap.test('does not fake live UDP success for host-only GoodWe configs', async () => {
  const runtime = await new GoodweIntegration().setup({ host: '192.168.1.50' }, {});
  const status = await runtime.callService!({ domain: 'goodwe', service: 'status', target: {} });
  const refresh = await runtime.callService!({ domain: 'goodwe', service: 'refresh', target: {} });

  expect(status.success).toBeTrue();
  expect((status.data as { online?: boolean }).online).toBeFalse();
  expect(refresh.success).toBeFalse();
  expect(refresh.error).toContain('Native GoodWe UDP/TCP transport is not implemented');
  await runtime.destroy();
});

tap.test('does not report command success for static GoodWe snapshots', async () => {
  const snapshot = GoodweMapper.toSnapshot({ config: {}, rawData, online: true, source: 'manual' });
  const runtime = await new GoodweIntegration().setup({ snapshot }, {});
  const result = await runtime.callService!({ domain: 'number', service: 'set_value', target: { entityId: 'number.runtime_goodwe_grid_export_limit' }, data: { value: 1000 } });

  expect(result.success).toBeFalse();
  expect(result.error!.includes('static snapshots/manual data are read-only')).toBeTrue();
  await runtime.destroy();
});

tap.test('delegates GoodWe controls to an injected command executor', async () => {
  const commands: IGoodweCommandRequest[] = [];
  const snapshot = GoodweMapper.toSnapshot({ config: {}, rawData, online: true, source: 'manual' });
  const runtime = await new GoodweIntegration().setup({
    snapshot,
    commandExecutor: {
      execute: async (commandArg) => {
        commands.push(commandArg);
        return { accepted: true };
      },
    },
  }, {});
  const result = await runtime.callService!({ domain: 'goodwe', service: 'set_operation_mode', target: {}, data: { operation_mode: 'eco' } });

  expect(result.success).toBeTrue();
  expect(commands[0].action).toEqual('set_operation_mode');
  expect(commands[0].operationMode).toEqual('eco');
  await runtime.destroy();
});

tap.test('builds snapshots from injected GoodWe client-like readers', async () => {
  const client = new GoodweClient({
    client: {
      model_name: 'GW10K-ET',
      serial_number: 'CLIENT123',
      firmware: 'FW1',
      arm_firmware: 'ARM1',
      read_runtime_data: async () => ({ ppv: 2500, active_power: 1600, e_day: 8.2 }),
      read_settings_data: async () => ({ grid_export_limit: 4000 }),
      sensors: () => [{ id_: 'ppv', name: 'PV Power', unit: 'W', kind: 'PV' }, { id_: 'e_day', name: 'Energy Today', unit: 'kWh' }],
      settings: () => [{ id_: 'grid_export_limit', name: 'Grid Export Limit', unit: 'W' }],
      get_operation_mode: async () => 0,
      get_operation_modes: async () => [0, 1, 2, 3],
      get_grid_export_limit: async () => 4000,
    },
  });
  const snapshot = await client.getSnapshot();

  expect(snapshot.source).toEqual('client');
  expect(snapshot.online).toBeTrue();
  expect(snapshot.inverter.serialNumber).toEqual('CLIENT123');
  expect(snapshot.sensors.find((sensorArg) => sensorArg.id === 'ppv')?.value).toEqual(2500);
  expect(snapshot.controls.gridExportLimit).toEqual(4000);
});

export default tap.start();
