/**
 * Inventory sync from the Prime Intellect availability API.
 *
 * Runs on an interval, upserting listings on their natural key so repeated
 * syncs converge rather than accumulating near-duplicates.
 *
 * Two decisions worth explaining.
 *
 * **Stale listings are marked, not deleted.** A listing that disappears
 * upstream has usually sold out rather than ceased to exist, and deleting it
 * would destroy the price history that makes the inventory useful for
 * negotiation. Anything not seen in this pass is marked `Unavailable`, keeping
 * the record and its history while removing it from search.
 *
 * **A failed sync is not fatal.** The upstream publishes no rate limits, so
 * some failures are expected. The job logs and waits for the next tick rather
 * than crashing the server that people are using.
 */
import { and, eq, inArray, lt, sql } from 'drizzle-orm';
import type { Database } from '@pig/db';
import { inventoryListings } from '@pig/db';
import { PrimeClient, mapListing } from '@pig/prime';
import type { Config } from '../lib/config';

export function startPrimeSync(config: Config, db: Database): () => void {
  if (!config.PRIME_SYNC_ENABLED || !config.PRIME_API_KEY) {
    if (config.PRIME_SYNC_ENABLED) {
      console.warn('[pig] Prime sync enabled but no API key — not starting.');
    }
    return () => {};
  }

  const client = new PrimeClient({
    apiKey: config.PRIME_API_KEY,
    baseUrl: config.PRIME_API_BASE,
    onRetry: ({ attempt, delayMs, reason }) =>
      console.warn(`[pig] prime retry ${attempt} in ${delayMs}ms (${reason})`),
  });

  let running = false;

  async function runOnce() {
    // Overlapping runs would fight over the same rows for no benefit.
    if (running) return;
    running = true;
    const startedAt = new Date();
    let upserted = 0;

    try {
      for await (const page of client.iterateGpuAvailability()) {
        const rows = page
          .map(mapListing)
          .filter((row): row is NonNullable<typeof row> => row !== null);
        if (rows.length === 0) continue;

        for (const row of rows) {
          await db
            .insert(inventoryListings)
            .values({
              ...row,
              socket: row.socket as 'PCIe' | null,
              source: 'prime_api',
              observedAt: startedAt,
            })
            .onConflictDoUpdate({
              target: [
                inventoryListings.externalCloudId,
                inventoryListings.gpuType,
                inventoryListings.socket,
                inventoryListings.gpuCount,
                inventoryListings.securityTier,
              ],
              set: {
                stockStatus: row.stockStatus,
                onDemandPriceCents: row.onDemandPriceCents,
                communityPriceCents: row.communityPriceCents,
                priceIsVariable: row.priceIsVariable,
                interconnectGbps: row.interconnectGbps,
                interconnectType: row.interconnectType,
                provisioningMinutes: row.provisioningMinutes,
                region: row.region,
                country: row.country,
                images: row.images,
                raw: row.raw,
                observedAt: startedAt,
                updatedAt: new Date(),
              },
            });
          upserted += 1;
        }
      }

      // Anything the provider stopped listing is out of stock, not gone.
      const stale = await db
        .update(inventoryListings)
        .set({ stockStatus: 'Unavailable', updatedAt: new Date() })
        .where(
          and(
            eq(inventoryListings.source, 'prime_api'),
            lt(inventoryListings.observedAt, startedAt),
            sql`${inventoryListings.stockStatus} <> 'Unavailable'`,
          ),
        )
        .returning({ id: inventoryListings.id });

      console.log(
        `[pig] prime sync: ${upserted} listing(s) upserted, ${stale.length} marked unavailable`,
      );
    } catch (error) {
      // Logged, not thrown. A provider outage must not take down the CRM.
      console.error('[pig] prime sync failed:', error instanceof Error ? error.message : error);
    } finally {
      running = false;
    }
  }

  // Delay the first run so startup is not competing with an outbound sync.
  const initial = setTimeout(() => void runOnce(), 10_000);
  const interval = setInterval(
    () => void runOnce(),
    config.PRIME_SYNC_INTERVAL_MINUTES * 60_000,
  );

  console.log(`[pig] prime sync every ${config.PRIME_SYNC_INTERVAL_MINUTES}m`);

  return () => {
    clearTimeout(initial);
    clearInterval(interval);
  };
}
