// src/lib/keywords/import/resolve-keyword-actions.ts — read-only keyword
// lookup by term, for the SERP import UX (filename-derived hint → real
// keyword row to pre-select). Mirrors the org-guard + id-build mechanics of
// brief-by-term-actions.ts, minus any write.
"use server";
import { eq } from "drizzle-orm";
import * as wasm from "import-core";
import { db } from "@/lib/db/client";
import { keywords } from "@/lib/db/domain-schema";
import { keywordId as buildKeywordId } from "@/lib/keywords/import";
import { getSitesForActiveOrg } from "@/lib/sites/access";

/**
 * Resolve a keyword on `siteId` by its display `term`: slugify it with the
 * SAME rule as the keyword ETL/queries (`wasm.slugify`, via the
 * `<siteId>-<slug>` id convention) and look it up.
 *
 * - Org guard: `siteId` must be a site visible to the active org
 *   (`getSitesForActiveOrg` — owner/admin see all, member sees only granted).
 *   A foreign `siteId` throws (mirrors `importBriefByTerm`).
 * - Read-only: no write, no cache invalidation.
 * - Returns `null` when the term has no usable slug or no keyword matches.
 */
export async function resolveKeywordByTermAction(
  siteId: string,
  term: string,
): Promise<{ id: string; term: string; country: string } | null> {
  // Org guard: the site must be visible to the active org.
  const visibleSiteIds = new Set(
    (await getSitesForActiveOrg()).map((s) => s.id),
  );
  if (!visibleSiteIds.has(siteId)) {
    throw new Error("Site does not belong to the active organization");
  }

  const slug = wasm.slugify(term);
  // No usable term/slug → nothing to match against.
  if (!slug) return null;

  const id = buildKeywordId(siteId, slug);
  const [row] = await db
    .select({
      id: keywords.id,
      term: keywords.term,
      country: keywords.country,
    })
    .from(keywords)
    .where(eq(keywords.id, id))
    .limit(1);

  return row ?? null;
}
