/**
 * Server-side ingestion guard. Used by /api/ai/submit and /api/submission-receive
 * to reject incoming submissions that contain a disallowed phrase from the
 * bb.disallowed_phrases table (competitor publications, banned exhibitors,
 * etc.).
 */

import { createAdminClient } from "./supabase/admin";

type Phrase = {
  phrase: string;
  category: string;
  match_mode: "word_boundary" | "substring" | "domain";
};

let cached: { rows: Phrase[]; expires: number } | null = null;
const CACHE_TTL_MS = 3 * 60 * 1000;

async function loadActivePhrases(): Promise<Phrase[]> {
  if (cached && cached.expires > Date.now()) return cached.rows;
  try {
    const svc = createAdminClient();
    const { data } = await svc
      .from("disallowed_phrases")
      .select("phrase, category, match_mode")
      .eq("active", true);
    const rows = (data || []) as Phrase[];
    cached = { rows, expires: Date.now() + CACHE_TTL_MS };
    return rows;
  } catch {
    return cached?.rows || [];
  }
}

function escapeRegex(s: string): string {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

export type Violation = { phrase: string; category: string };

/** Returns the list of phrases the text violates (empty if clean). */
export async function findViolations(text: string): Promise<Violation[]> {
  if (!text) return [];
  const phrases = await loadActivePhrases();
  const out: Violation[] = [];
  for (const p of phrases) {
    const esc = escapeRegex(p.phrase);
    let re: RegExp;
    if (p.match_mode === "word_boundary") {
      re = new RegExp(`(^|[^A-Za-z0-9])(${esc})(?![A-Za-z0-9])`, "i");
    } else if (p.match_mode === "domain") {
      re = new RegExp(`(?:https?://)?(?:[\\w-]+\\.)?${esc}\\b`, "i");
    } else {
      re = new RegExp(esc, "i");
    }
    if (re.test(text)) out.push({ phrase: p.phrase, category: p.category });
  }
  return out;
}

/** Throw-style helper: short-circuits an API route on first violation. */
export async function assertNoViolations(text: string): Promise<{ ok: true } | { ok: false; violations: Violation[] }> {
  const v = await findViolations(text);
  return v.length === 0 ? { ok: true } : { ok: false, violations: v };
}
