// src/lib/keywords/enrich-status-actions.ts — lecture org-scopée du rail de
// statut d'enrichissement (spinner par-ligne du réservoir). Seule surface
// réseau du rail : `setEnrichStatus`/`clearEnrichStatus` restent `server-only`,
// pilotés par les workers de sync. AUCUN `deps` exposé.
"use server";
import { and, eq, inArray } from "drizzle-orm";
import { db } from "@/lib/db/client";
import { keywords } from "@/lib/db/domain-schema";
import { assertSiteInActiveOrg } from "@/lib/sites/assert-site";
import type { KeywordEnrichment } from "./types";

/** Cap dur d'ids par requête (garde-fou bind-params + payload). */
const MAX_IDS = 500;

/**
 * Renvoie une map `id → enrichment` pour les mots-clés demandés du site.
 * Garde tenancy : le site doit appartenir à l'org active (fail-closed). Le
 * SELECT filtre AUSSI sur `siteId` — un id appartenant à un autre site n'est
 * jamais renvoyé, même s'il est demandé (protection cross-site au niveau SQL).
 * Cap à 500 ids (les surplus sont ignorés). Tableau vide → map vide sans
 * requête. Les mots-clés sans état renvoient `{}`.
 */
export async function fetchEnrichStatusesAction(
  siteId: string,
  keywordIds: string[],
): Promise<Record<string, KeywordEnrichment>> {
  await assertSiteInActiveOrg(siteId);
  if (keywordIds.length === 0) return {};
  const ids = keywordIds.slice(0, MAX_IDS);
  const rows = await db
    .select({ id: keywords.id, enrichment: keywords.enrichment })
    .from(keywords)
    .where(and(eq(keywords.siteId, siteId), inArray(keywords.id, ids)));
  const out: Record<string, KeywordEnrichment> = {};
  for (const row of rows) {
    out[row.id] = row.enrichment ?? {};
  }
  return out;
}
