import type { FleetState } from './fleet-state.js';
import { ensureHostState, stampLastSeen } from './fleet-state.js';
import type { getSql } from '../db.js';
import { jsonbObject } from './jsonb.js';

export async function rebuildFleetFromDB(fleet: FleetState, sql: ReturnType<typeof getSql>): Promise<void> {
  // Latest event per (provider, model) via DISTINCT ON -- one row per model, the
  // truly newest, instead of one-per-(provider,model,state) which over-reads and
  // can tie on identical clock_timestamp() values (REV5).
  const modelEvents = await sql<{ provider_id: string; model: string; state: string; ts: string; detail: string }[]>`
    SELECT DISTINCT ON (provider_id, model) provider_id, model, state, ts, detail
    FROM control_model_events
    ORDER BY provider_id, model, ts DESC
  `;

  for (const row of modelEvents) {
    const state = ensureHostState(fleet, row.provider_id);
    state.liveness = 'down';
    stampLastSeen(state);
    // row.detail is jsonb (porsager returns it parsed); jsonbObject tolerates
    // both a parsed object and a JSON string.
    const detail: unknown = jsonbObject(row.detail);
    // B4: ttlDeadline recalculation. Use event timestamp so the deadline reflects
    // when the model was actually loaded, not when we rebuild.
    const ttl = (detail as { ttl?: number })?.ttl;
    const eventTs = new Date(row.ts).getTime();
    const ttlDeadline = ttl ? new Date(eventTs + ttl * 1000) : null;
    state.models.set(row.model, {
      model: row.model,
      state: row.state,
      ts: new Date(row.ts),
      ttlDeadline,
      inflight: 0,
    });
  }

  const lastRequests = await sql<{ provider_id: string; ts: string }[]>`
    SELECT provider_id, ts FROM control_requests
    WHERE ts IN (
      SELECT MAX(ts) FROM control_requests GROUP BY provider_id
    )
    ORDER BY ts DESC
  `;

  for (const row of lastRequests) {
    const state = ensureHostState(fleet, row.provider_id);
    stampLastSeen(state);
  }

  const lastPerf = await sql<{ provider_id: string; ts: string }[]>`
    SELECT provider_id, ts FROM control_perf_samples
    WHERE ts IN (
      SELECT MAX(ts) FROM control_perf_samples GROUP BY provider_id
    )
    ORDER BY ts DESC
  `;

  for (const row of lastPerf) {
    const state = ensureHostState(fleet, row.provider_id);
    stampLastSeen(state);
  }
}
