/**
 * i18n repository — Cosmos DB CRUD for translations and locales.
 * Fallback chain: requested locale → language-only → 'en'.
 */

import { getRegisteredContainer } from '@bytelyst/cosmos';
import type { TranslationDoc, LocaleDoc, BulkImportInput, CreateLocaleInput } from './types.js';

// ── Container Access ──────────────────────────────────────────

function getTranslationsContainer() {
  return getRegisteredContainer('translations');
}

function getLocalesContainer() {
  return getRegisteredContainer('i18n_locales');
}

// ── Locale CRUD ──────────────────────────────────────────────

export async function listLocales(productId: string): Promise<LocaleDoc[]> {
  const { resources } = await getLocalesContainer()
    .items.query<LocaleDoc>({
      query: 'SELECT * FROM c WHERE c.productId = @pid ORDER BY c.locale ASC',
      parameters: [{ name: '@pid', value: productId }],
    })
    .fetchAll();
  return resources;
}

export async function getLocale(locale: string): Promise<LocaleDoc | null> {
  try {
    const { resource } = await getLocalesContainer().item(locale, locale).read<LocaleDoc>();
    return resource ?? null;
  } catch {
    return null;
  }
}

export async function createLocale(
  productId: string,
  input: CreateLocaleInput
): Promise<LocaleDoc> {
  const now = new Date().toISOString();
  const doc: LocaleDoc = {
    id: input.locale,
    locale: input.locale,
    name: input.name,
    nativeName: input.nativeName,
    direction: input.direction ?? 'ltr',
    productId,
    enabled: input.enabled ?? true,
    createdAt: now,
    updatedAt: now,
  };
  await getLocalesContainer().items.create(doc);
  return doc;
}

// ── Translation CRUD ─────────────────────────────────────────

function translationId(locale: string, key: string): string {
  return `${locale}:${key}`;
}

function extractNamespace(key: string): string {
  const idx = key.indexOf('.');
  return idx > 0 ? key.substring(0, idx) : key;
}

export async function getTranslations(
  locale: string,
  productId: string,
  namespace?: string
): Promise<Record<string, string>> {
  const conditions = ['c.locale = @loc', 'c.productId = @pid'];
  const params = [
    { name: '@loc', value: locale },
    { name: '@pid', value: productId },
  ];

  if (namespace) {
    conditions.push('c.namespace = @ns');
    params.push({ name: '@ns', value: namespace });
  }

  const { resources } = await getTranslationsContainer()
    .items.query<TranslationDoc>({
      query: `SELECT * FROM c WHERE ${conditions.join(' AND ')}`,
      parameters: params,
    })
    .fetchAll();

  const result: Record<string, string> = {};
  for (const doc of resources) {
    result[doc.key] = doc.value;
  }
  return result;
}

export async function getTranslationsWithFallback(
  locale: string,
  productId: string,
  namespace?: string
): Promise<{ translations: Record<string, string>; resolvedLocale: string }> {
  // Try exact locale (e.g. 'fr-CA')
  let translations = await getTranslations(locale, productId, namespace);
  if (Object.keys(translations).length > 0) {
    return { translations, resolvedLocale: locale };
  }

  // Try language-only (e.g. 'fr')
  const langOnly = locale.split('-')[0];
  if (langOnly !== locale) {
    translations = await getTranslations(langOnly, productId, namespace);
    if (Object.keys(translations).length > 0) {
      return { translations, resolvedLocale: langOnly };
    }
  }

  // Fallback to 'en'
  if (langOnly !== 'en') {
    translations = await getTranslations('en', productId, namespace);
    return { translations, resolvedLocale: 'en' };
  }

  return { translations: {}, resolvedLocale: locale };
}

export async function upsertTranslation(
  locale: string,
  key: string,
  value: string,
  productId: string
): Promise<TranslationDoc> {
  const id = translationId(locale, key);
  const namespace = extractNamespace(key);
  const now = new Date().toISOString();

  // Try to read existing
  try {
    const { resource } = await getTranslationsContainer().item(id, locale).read<TranslationDoc>();
    if (resource) {
      const updated: TranslationDoc = {
        ...resource,
        value,
        updatedAt: now,
      };
      await getTranslationsContainer().item(id, locale).replace(updated);
      return updated;
    }
  } catch {
    // Does not exist — create
  }

  const doc: TranslationDoc = {
    id,
    locale,
    key,
    namespace,
    value,
    productId,
    createdAt: now,
    updatedAt: now,
  };
  await getTranslationsContainer().items.create(doc);
  return doc;
}

export async function bulkImport(
  locale: string,
  productId: string,
  input: BulkImportInput
): Promise<{ imported: number; skipped: number }> {
  let imported = 0;
  let skipped = 0;

  for (const [key, value] of Object.entries(input.translations)) {
    const id = translationId(locale, key);

    if (!input.overwrite) {
      // Check if already exists
      try {
        const { resource } = await getTranslationsContainer()
          .item(id, locale)
          .read<TranslationDoc>();
        if (resource) {
          skipped++;
          continue;
        }
      } catch {
        // Does not exist — proceed with create
      }
    }

    await upsertTranslation(locale, key, value, productId);
    imported++;
  }

  return { imported, skipped };
}

export async function deleteTranslation(locale: string, key: string): Promise<boolean> {
  const id = translationId(locale, key);
  try {
    await getTranslationsContainer().item(id, locale).delete();
    return true;
  } catch {
    return false;
  }
}
