import { and, eq, inArray } from "drizzle-orm";
import { schema, type Database } from "@app/database";
import { loadLocalePreferences } from "./localeContext.js";

/**
 * Innehållsspråk (i18n-spec §11–14): svensk källtext är sanningen, publicerade
 * översättningar är vyer. Upplösning: exakt tagg ("en-US") → primärt språk
 * ("en") → svensk källa. Endast status=published serveras till användare.
 */

/** "en-US" -> ["en-US", "en"], "sv" -> ["sv"]. */
export function languageCandidates(languageTag: string): string[] {
  const primary = languageTag.split("-")[0] ?? languageTag;
  return primary === languageTag ? [languageTag] : [languageTag, primary];
}

export async function userLanguageTag(db: Database, userId: string): Promise<string> {
  const prefs = await loadLocalePreferences(db, userId);
  return prefs.languageTag;
}

export interface ResolvedRecipeText {
  language: string;
  title: string;
  description: string | null;
  storageGuidance: string | null;
  /** stepNumber -> { instruction, tip } */
  steps: Map<number, { instruction: string; tip: string | null }>;
}

/**
 * Hämtar publicerad receptöversättning för användarens språk, eller null om
 * svensk källa ska användas. En DB-runda för texterna + en för stegen.
 */
export async function resolveRecipeTranslation(
  db: Database,
  recipeId: string,
  languageTag: string,
): Promise<ResolvedRecipeText | null> {
  const candidates = languageCandidates(languageTag);
  if (candidates.includes("sv")) return null;

  const rows = await db
    .select()
    .from(schema.recipeTranslations)
    .where(
      and(
        eq(schema.recipeTranslations.recipeId, recipeId),
        inArray(schema.recipeTranslations.languageTag, candidates),
        eq(schema.recipeTranslations.status, "published"),
      ),
    );
  if (rows.length === 0) return null;
  const best =
    candidates.map((c) => rows.find((r) => r.languageTag === c)).find(Boolean) ?? rows[0]!;

  const stepRows = await db
    .select()
    .from(schema.recipeStepTranslations)
    .where(
      and(
        eq(schema.recipeStepTranslations.recipeId, recipeId),
        eq(schema.recipeStepTranslations.languageTag, best.languageTag),
      ),
    );
  return {
    language: best.languageTag,
    title: best.title,
    description: best.description,
    storageGuidance: best.storageGuidance,
    steps: new Map(stepRows.map((s) => [s.stepNumber, { instruction: s.instruction, tip: s.tip }])),
  };
}

/**
 * Ingrediensnamn för användarens språk: Map ingredientId -> namn.
 * Saknade id:n behåller svenskt namn (fallback sker hos anroparen).
 */
export async function resolveIngredientNames(
  db: Database,
  ingredientIds: string[],
  languageTag: string,
): Promise<Map<string, string>> {
  const candidates = languageCandidates(languageTag);
  if (candidates.includes("sv") || ingredientIds.length === 0) return new Map();
  const rows = await db
    .select({
      ingredientId: schema.ingredientTranslations.ingredientId,
      languageTag: schema.ingredientTranslations.languageTag,
      name: schema.ingredientTranslations.name,
    })
    .from(schema.ingredientTranslations)
    .where(
      and(
        inArray(schema.ingredientTranslations.ingredientId, ingredientIds),
        inArray(schema.ingredientTranslations.languageTag, candidates),
        eq(schema.ingredientTranslations.status, "published"),
      ),
    );
  const out = new Map<string, string>();
  for (const candidate of [...candidates].reverse()) {
    for (const r of rows) if (r.languageTag === candidate) out.set(r.ingredientId, r.name);
  }
  return out;
}
