/**
 * i18n routes.
 * Public: get translations, list locales. Admin: upsert, bulk import, manage locales.
 */

import type { FastifyInstance } from 'fastify';
import { UnauthorizedError, ForbiddenError, NotFoundError } from '../../lib/errors.js';
import { getRequestProductId, getRequestProductIdForPublic } from '../../lib/request-context.js';
import { UpsertTranslationSchema, BulkImportSchema, CreateLocaleSchema } from './types.js';
import {
  listLocales,
  getTranslationsWithFallback,
  upsertTranslation,
  bulkImport,
  deleteTranslation,
  createLocale,
} from './repository.js';

function requireAdmin(req: { jwtPayload?: { sub: string; role?: string } }): string {
  if (!req.jwtPayload?.sub) throw new UnauthorizedError('Authentication required');
  if (req.jwtPayload.role !== 'admin') throw new ForbiddenError('Admin access required');
  return req.jwtPayload.sub;
}

export async function i18nRoutes(app: FastifyInstance): Promise<void> {
  // ── Public: List available locales ────────────────────────
  app.get('/i18n/locales', async req => {
    const productId = getRequestProductIdForPublic(req);
    const locales = await listLocales(productId);
    return locales.filter(l => l.enabled);
  });

  // ── Public: Get translations for locale ──────────────────
  app.get<{ Params: { locale: string } }>('/i18n/:locale', async req => {
    const productId = getRequestProductIdForPublic(req);
    return getTranslationsWithFallback(req.params.locale, productId);
  });

  // ── Public: Get translations for locale + namespace ──────
  app.get<{ Params: { locale: string; namespace: string } }>(
    '/i18n/:locale/:namespace',
    async req => {
      const productId = getRequestProductIdForPublic(req);
      return getTranslationsWithFallback(req.params.locale, productId, req.params.namespace);
    }
  );

  // ── Admin: Upsert translation ────────────────────────────
  app.put<{ Params: { locale: string; key: string } }>('/admin/i18n/:locale/:key', async req => {
    requireAdmin(req);
    const productId = getRequestProductId(req);
    const { value } = UpsertTranslationSchema.parse(req.body);
    return upsertTranslation(req.params.locale, req.params.key, value, productId);
  });

  // ── Admin: Bulk import translations ──────────────────────
  app.post<{ Params: { locale: string } }>('/admin/i18n/:locale/import', async req => {
    requireAdmin(req);
    const productId = getRequestProductId(req);
    const input = BulkImportSchema.parse(req.body);
    return bulkImport(req.params.locale, productId, input);
  });

  // ── Admin: Delete translation ────────────────────────────
  app.delete<{ Params: { locale: string; key: string } }>(
    '/admin/i18n/:locale/:key',
    async (req, reply) => {
      requireAdmin(req);
      const ok = await deleteTranslation(req.params.locale, req.params.key);
      if (!ok) throw new NotFoundError('Translation not found');
      reply.status(204);
    }
  );

  // ── Admin: Create locale ─────────────────────────────────
  app.post('/admin/i18n/locales', async (req, reply) => {
    requireAdmin(req);
    const productId = getRequestProductId(req);
    const input = CreateLocaleSchema.parse(req.body);
    const locale = await createLocale(productId, input);
    reply.status(201);
    return locale;
  });
}
