import type { FleetState } from './fleet-state.js';
import { ensureHostState, stampLastSeen, incrementSeq } from './fleet-state.js';
import type { DeltaEmitter } from './delta-emitter.js';
import type { getSql } from '../db.js';
import type { loadConfig } from '../config.js';

export async function pollPerformance(
  sql: ReturnType<typeof getSql>,
  config: ReturnType<typeof loadConfig>,
  providerId: string,
  baseUrl: string,
  fleet: FleetState,
  emitter: DeltaEmitter,
): Promise<void> {
  void config;
  const state = ensureHostState(fleet, providerId);

  const watermark = await sql<{ ts: string | null }[]>`
    SELECT MAX(ts) AS ts FROM control_perf_samples WHERE provider_id = ${providerId}
  `;

  // porsager returns timestamptz as a Date object; interpolating it raw yields
  // Date.toString() which llama-swap rejects with 400.
  const afterParam = watermark[0]?.ts
    ? `?after=${encodeURIComponent(new Date(watermark[0].ts).toISOString())}`
    : '';
  const url = `${baseUrl}/api/performance${afterParam}`;

  try {
    const fetchSignal = AbortSignal.timeout(10_000);
    const res = await fetch(url, { signal: fetchSignal });
    if (!res.ok) return;

    const data = await res.json() as { gpu_stats?: unknown[]; sys_stats?: unknown[] } | null;
    if (!data) return;

    const gpuMap = new Map<string, unknown>();
    for (const g of data.gpu_stats ?? []) {
      const gpu = g as { timestamp?: string };
      if (gpu.timestamp) {
        gpuMap.set(gpu.timestamp, g);
      }
    }

    const sysMap = new Map<string, unknown>();
    for (const s of data.sys_stats ?? []) {
      const sys = s as { timestamp?: string };
      if (sys.timestamp) {
        sysMap.set(sys.timestamp, s);
      }
    }

    const allTimestamps = new Set([...gpuMap.keys(), ...sysMap.keys()]);
    if (allTimestamps.size === 0) return;

    stampLastSeen(state);

    for (const ts of allTimestamps) {
      const gpu = gpuMap.get(ts) ?? null;
      const sys = sysMap.get(ts) ?? null;

      await sql`
        INSERT INTO control_perf_samples (provider_id, ts, gpu, sys)
        VALUES (${providerId}, ${ts}, ${sql.json(gpu as never)}, ${sql.json(sys as never)})
        ON CONFLICT (provider_id, ts) DO NOTHING
      `;

      const seq = incrementSeq(state);
      emitter.publish({
        type: 'control_perf' as const,
        seq,
        providerId,
        ts,
        gpu,
        sys,
      });
    }
  } catch (err) {
    const msg = (err as Error).message ?? String(err);
    console.warn({ providerId, err: msg }, 'fleet: perf poll failed');
  }
}
