import { expect, tap } from '@git.zone/tstest/tapbundle';
import { ImeonInverterClient, ImeonInverterIntegration, imeonInverterProfile, type IImeonInverterSnapshot } from '../../ts/integrations/imeon_inverter/index.js';

tap.test('logs in, polls live Imeon HTTP endpoints, and maps HA sensor/select keys', async () => {
  const originalFetch = globalThis.fetch;
  const requests: Array<{ url: string; method: string; cookie?: string; body?: unknown }> = [];
  globalThis.fetch = (async (inputArg: RequestInfo | URL, initArg?: RequestInit) => {
    const url = new URL(String(inputArg));
    const headers = initArg?.headers as Record<string, string> | undefined;
    requests.push({ url: url.toString(), method: initArg?.method || 'GET', cookie: headers?.cookie, body: initArg?.body });

    if (url.pathname === '/login') {
      expect(String(initArg?.body)).toContain('email=user%40local');
      return jsonResponse({ accessGranted: true }, 200, { 'set-cookie': 'session=abc; Path=/' });
    }
    if (url.pathname === '/data') {
      return jsonResponse({ type: 'Imeon 9.12', software: '1.8.1.0', serial: 'IMEON123', max_ac_charging_current: 16, injection_power: 2500, enable_status: { discharge_night: '1', charge_bat_with_grid: '0' } });
    }
    if (url.pathname === '/api/battery') {
      return imeonResult({ power: 123, soc: 88, status: 'charging', stored: 20, consumed: 10 });
    }
    if (url.pathname === '/api/grid') {
      expect(url.searchParams.get('threephase')).toEqual('true');
      return imeonResult({ current_l1: 1, current_l2: 2, current_l3: 3, frequency: 50, voltage_l1: 230, voltage_l2: 231, voltage_l3: 232 });
    }
    if (url.pathname === '/api/pv') {
      return imeonResult({ consumed: 4, injected: 5, power_1: 100, power_2: 110, power_total: 210 });
    }
    if (url.pathname === '/api/input') {
      return imeonResult({ power_l1: 1, power_l2: 2, power_l3: 3, power_total: 6 });
    }
    if (url.pathname === '/api/output') {
      return imeonResult({ current_l1: 1, current_l2: 2, current_l3: 3, frequency: 50, power_l1: 10, power_l2: 20, power_l3: 30, power_total: 60, voltage_l1: 230, voltage_l2: 231, voltage_l3: 232 });
    }
    if (url.pathname === '/api/em') {
      return imeonResult({ power: 42 });
    }
    if (url.pathname === '/api/temp') {
      return imeonResult({ air_temperature: 21, component_temperature: 33 });
    }
    if (url.pathname === '/api/timeline') {
      return imeonResult({ type_msg: 'good_1' });
    }
    if (url.pathname === '/api/energy') {
      return imeonResult({ pv: 1000, grid_injected: 200, grid_consumed: 300, building_consumption: 400, battery_stored: 500, battery_consumed: 600 });
    }
    if (url.pathname === '/api/forecast') {
      return imeonResult({ cons_remaining_today: 700, prod_remaining_today: 800 });
    }
    if (url.pathname === '/api/monitor') {
      return url.searchParams.get('time') === 'minute'
        ? imeonResult({ building_consumption: 111, grid_consumption: 222, grid_injection: 333, grid_power_flow: 444, solar_production: 555 })
        : imeonResult({ self_consumption: 67, self_sufficiency: 89 });
    }
    if (url.pathname === '/api/manager') {
      return imeonResult({ inverter_state: 'grid_consumption', inverter_mode: 'smg' });
    }
    if (url.pathname === '/api/smartload') {
      return imeonResult({ active: false });
    }
    if (url.pathname === '/api/set') {
      expect(initArg?.body instanceof FormData).toBeTrue();
      expect((initArg?.body as FormData).get('inverter_mode')).toEqual('bup');
      return new Response(JSON.stringify({ success: true }), { status: 200, headers: { 'content-type': 'application/json' } });
    }
    return jsonResponse({ message: 'not found' }, 404);
  }) as typeof globalThis.fetch;

  try {
    const client = new ImeonInverterClient({ host: 'imeon.local', username: 'user@local', password: 'password' });
    const snapshot = await client.getSnapshot();
    const command = await client.execute({ domain: 'select', service: 'select_option', target: {}, data: { option: 'backup' } });
    const runtime = await new ImeonInverterIntegration().setup({ host: 'imeon.local', username: 'user@local', password: 'password' }, {});
    const status = await runtime.callService!({ domain: 'imeon_inverter', service: 'status', target: {} });

    expect(snapshot.online).toBeTrue();
    expect(snapshot.source).toEqual('http');
    expect(snapshot.device.serialNumber).toEqual('IMEON123');
    expect(snapshot.entities.find((entityArg) => entityArg.id === 'battery_power')?.state).toEqual(123);
    expect(snapshot.entities.find((entityArg) => entityArg.id === 'manager_inverter_mode')?.state).toEqual('smart_grid');
    expect(command.success).toBeTrue();
    expect((status.data as IImeonInverterSnapshot).online).toBeTrue();
    expect(requests.some((requestArg) => requestArg.url.includes('/api/battery?time=minute') && requestArg.cookie === 'session=abc')).toBeTrue();
    expect(requests.some((requestArg) => requestArg.url.includes('/api/set'))).toBeTrue();
    await runtime.destroy();
  } finally {
    globalThis.fetch = originalFetch;
  }
});

tap.test('documents Imeon native HTTP support and safe unsupported cases', async () => {
  const localApi = imeonInverterProfile.metadata.localApi as { implemented: string[]; explicitUnsupported: string[] };

  expect(localApi.implemented.some((itemArg) => itemArg.includes('POST /login'))).toBeTrue();
  expect(localApi.implemented.some((itemArg) => itemArg.includes('POST /api/set'))).toBeTrue();
  expect(localApi.explicitUnsupported.some((itemArg) => itemArg.includes('ETH port access only'))).toBeTrue();
});

const imeonResult = (valueArg: Record<string, unknown>): Response => jsonResponse({ result: JSON.stringify(valueArg) });

const jsonResponse = (valueArg: unknown, statusArg = 200, headersArg: Record<string, string> = {}): Response => new Response(JSON.stringify(valueArg), {
  status: statusArg,
  headers: { 'content-type': 'application/json', ...headersArg },
});

export default tap.start();
