/**
 * search.ts — Per-locale tsvector population for deal_translations.search.
 *
 * Called by translateDealFields after writing the translation row.
 * Reads `languages.search_config` to pick the correct Postgres regconfig,
 * then builds a weighted tsvector:
 *   title           → weight A
 *   description     → weight B
 *   specialInstructions → weight C
 *
 * The regconfig identifier comes only from KNOWN_REGCONFIGS — never from
 * user input — so sql.raw() is safe.
 */

import { sql, eq } from 'drizzle-orm';
import type { DrizzleClient } from '@/server/db/client.js';
import { languages } from '@/server/db/schema.js';

// Exhaustive allowlist of Postgres text-search configurations we support.
// ANY value read from languages.search_config is checked against this list;
// unknown values fall back to 'simple'.
export const KNOWN_REGCONFIGS = [
  'simple',
  'english',
  'simple_unaccent',
  'arabic',
  'russian',
] as const;

export type KnownRegconfig = (typeof KNOWN_REGCONFIGS)[number];

function isKnownRegconfig(v: string): v is KnownRegconfig {
  return (KNOWN_REGCONFIGS as readonly string[]).includes(v);
}

/**
 * Reads the per-locale regconfig from the `languages` table, builds a
 * weighted tsvector, and UPDATEs `deal_translations.search`.
 *
 * Safe-to-call even when the translation row has NULL fields — COALESCE('')
 * ensures to_tsvector never receives NULL.
 *
 * @param db      DrizzleClient (non-transactional; DO worker passes DoDbClient).
 * @param dealId  UUID of the deal.
 * @param locale  BCP-47 locale code matching `languages.code`.
 */
export async function recomputeSearchTsvector(
  db: DrizzleClient,
  dealId: string,
  locale: string,
): Promise<void> {
  // Resolve regconfig for this locale from the languages table.
  const [lang] = await db
    .select({ searchConfig: languages.searchConfig })
    .from(languages)
    .where(eq(languages.code, locale))
    .limit(1);

  const rawConfig = lang?.searchConfig ?? '';
  const regconfig: KnownRegconfig = isKnownRegconfig(rawConfig) ? rawConfig : 'simple';

  // Build and execute the UPDATE with a weighted tsvector expression.
  // sql.raw() is used ONLY for the regconfig identifier, which is validated against
  // KNOWN_REGCONFIGS above — never derived from user input.
  await db.execute(sql`
    UPDATE deal_translations
       SET search = (
             setweight(to_tsvector(${sql.raw(`'${regconfig}'::regconfig`)}, coalesce(title, '')), 'A')
          || setweight(to_tsvector(${sql.raw(`'${regconfig}'::regconfig`)}, coalesce(description, '')), 'B')
          || setweight(to_tsvector(${sql.raw(`'${regconfig}'::regconfig`)}, coalesce(special_instructions, '')), 'C')
           )
     WHERE deal_id = ${dealId}
       AND locale  = ${locale}
  `);
}
