#!/usr/bin/env node
/**
 * Generates i18n maps for the native mobile app from the web source of truth.
 *
 * Source of truth: `frontend/src/i18n/locales/*.json`
 *
 * Output:
 * - `mobile-app/shared/src/commonMain/kotlin/de/tsschulz/tt_tagebuch/shared/i18n/MobileStrings.kt`
 *
 * Notes:
 * - German (`de`) is the canonical key set.
 * - Missing locale keys fall back to German at generation time so every mobile locale is complete.
 */

const fs = require('fs');
const path = require('path');

const ROOT = path.resolve(__dirname, '..');
const SOURCE_DIR = path.join(ROOT, 'frontend', 'src', 'i18n', 'locales');
const OUT = path.join(
  ROOT,
  'mobile-app',
  'shared',
  'src',
  'commonMain',
  'kotlin',
  'de',
  'tsschulz',
  'tt_tagebuch',
  'shared',
  'i18n',
  'MobileStrings.kt'
);

const LOCALE_LABELS = {
  'de': 'Deutsch',
  'de-CH': 'Deutsch (Schweiz)',
  'de-extended': 'Deutsch (erweitert)',
  'en-US': 'English (US)',
  'en-GB': 'English (UK)',
  'en-AU': 'English (AU)',
  'es': 'Español',
  'fr': 'Français',
  'it': 'Italiano',
  'pl': 'Polski',
  'ja': '日本語',
  'th': 'ไทย',
  'tl': 'Tagalog',
  'fil': 'Filipino',
  'zh': '中文',
};

const MOBILE_STRINGS = {
  de: {
    'mobile.add': 'Hinzufügen',
    'mobile.appLoading': 'App wird geladen',
    'mobile.cancel': 'Abbrechen',
    'mobile.clubRequest': 'Zugriff anfragen',
    'mobile.clubRequested': 'Angefragt',
    'mobile.createDiaryEntry': 'Eintrag erstellen',
    'mobile.deleteNote': 'Notiz löschen',
    'mobile.deleteTag': 'Tag entfernen',
    'mobile.editTimes': 'Zeiten bearbeiten',
    'mobile.emailAndPasswordRequired': 'E-Mail und Passwort sind erforderlich',
    'mobile.entry': 'Eintrag',
    'mobile.language': 'Sprache',
    'mobile.lastTraining': 'Letztes Training',
    'mobile.loginInProgress': 'Anmelden...',
    'mobile.loginFailed': 'Login fehlgeschlagen',
    'mobile.more': 'Mehr',
    'mobile.new': 'Neu',
    'mobile.newNote': 'Neue Notiz',
    'mobile.newTag': 'Neuer Tag',
    'mobile.noDiaryEntries': 'Noch keine Tagebuch-Einträge',
    'mobile.noMembers': 'Keine Mitglieder gefunden',
    'mobile.noResults': 'Keine Treffer',
    'mobile.noTimes': 'Keine Zeiten',
    'mobile.offlineCacheHint': 'Keine Verbindung – zuletzt geladene Daten.',
    'mobile.participationTop': 'Top Teilnahmen',
    'mobile.refresh': 'Aktualisieren',
    'mobile.requestedAccess': 'Angefragt',
    'mobile.role': 'Rolle',
    'mobile.saveEntry': 'Speichern',
    'mobile.search': 'Suche',
    'mobile.select': 'Auswählen',
    'mobile.sessionCheck': 'Session prüfen',
    'mobile.sessionCheckFailed': 'Session check fehlgeschlagen',
    'mobile.sessionInvalid': 'Session ungültig',
    'mobile.sessionValid': 'Session gültig',
    'mobile.status': 'Status',
    'mobile.active': 'Aktiv',
    'mobile.inactive': 'Inaktiv',
    'mobile.user': 'Benutzer',
  },
  en: {
    'mobile.add': 'Add',
    'mobile.appLoading': 'Loading app',
    'mobile.cancel': 'Cancel',
    'mobile.clubRequest': 'Request access',
    'mobile.clubRequested': 'Requested',
    'mobile.createDiaryEntry': 'Create entry',
    'mobile.deleteNote': 'Delete note',
    'mobile.deleteTag': 'Remove tag',
    'mobile.editTimes': 'Edit times',
    'mobile.emailAndPasswordRequired': 'Email and password are required',
    'mobile.entry': 'Entry',
    'mobile.language': 'Language',
    'mobile.lastTraining': 'Last training',
    'mobile.loginInProgress': 'Signing in...',
    'mobile.loginFailed': 'Login failed',
    'mobile.more': 'More',
    'mobile.new': 'New',
    'mobile.newNote': 'New note',
    'mobile.newTag': 'New tag',
    'mobile.noDiaryEntries': 'No diary entries yet',
    'mobile.noMembers': 'No members found',
    'mobile.noResults': 'No results',
    'mobile.noTimes': 'No times',
    'mobile.offlineCacheHint': 'No connection – showing last loaded data.',
    'mobile.participationTop': 'Top attendance',
    'mobile.refresh': 'Refresh',
    'mobile.requestedAccess': 'Requested',
    'mobile.role': 'Role',
    'mobile.saveEntry': 'Save',
    'mobile.search': 'Search',
    'mobile.select': 'Select',
    'mobile.sessionCheck': 'Check session',
    'mobile.sessionCheckFailed': 'Session check failed',
    'mobile.sessionInvalid': 'Session invalid',
    'mobile.sessionValid': 'Session valid',
    'mobile.status': 'Status',
    'mobile.active': 'Active',
    'mobile.inactive': 'Inactive',
    'mobile.user': 'User',
  },
  es: {
    'mobile.offlineCacheHint': 'Sin conexión: se muestran los datos cargados por última vez.',
  },
  fr: {
    'mobile.offlineCacheHint': 'Pas de connexion – affichage des données du dernier chargement.',
  },
  it: {
    'mobile.offlineCacheHint': 'Nessuna connessione – dati dell’ultimo caricamento.',
  },
  pl: {
    'mobile.offlineCacheHint': 'Brak połączenia – wyświetlane ostatnio wczytane dane.',
  },
  ja: {
    'mobile.offlineCacheHint': 'ネットワークに接続されていません。最後に読み込んだデータを表示しています。',
  },
  th: {
    'mobile.offlineCacheHint': 'ไม่มีการเชื่อมต่อ – แสดงข้อมูลที่โหลดล่าสุด',
  },
  tl: {
    'mobile.offlineCacheHint': 'Walang koneksyon – ipinapakita ang huling na-load na datos.',
  },
  fil: {
    'mobile.offlineCacheHint': 'Walang koneksyon – ipinapakita ang huling na-load na datos.',
  },
  zh: {
    'mobile.offlineCacheHint': '无网络连接，显示上次加载的数据。',
  },
};

/** Kalender-Tab (CalendarScreen.kt): eigene Übersetzungen pro Locale, damit nicht nur Deutsch aus dem Basis-Flat greift. */
const MOBILE_CALENDAR_I18N = {
  de: {
    'mobile.calendarSourceDiary': 'Tagebuch',
    'mobile.calendarSourceTrainingTimes': 'Trainingszeiten',
    'mobile.calendarSourceCancellations': 'Trainingsausfälle',
    'mobile.calendarSourceTournaments': 'Turniere',
    'mobile.calendarSourceMatches': 'Punktspiele',
    'mobile.calendarSourceOfficial': 'Turnierteilnahmen',
    'mobile.calendarSourceHolidays': 'Ferien/Feiertage',
    'mobile.calendarLegendTraining': 'Training',
    'mobile.calendarLegendTournament': 'Turnier',
    'mobile.calendarLegendOfficial': 'Teilnahme',
    'mobile.calendarLegendMatch': 'Punktspiel',
    'mobile.calendarLegendHoliday': 'Feiertag',
    'mobile.calendarLegendSchool': 'Ferien',
    'mobile.calendarLegendCancellation': 'Ausfall',
    'mobile.calendarTitle': 'Kalender',
    'mobile.calendarSubtitle': 'Training, Turniere, Spiele und Feiertage im Monat.',
    'mobile.calendarToday': 'Heute',
    'mobile.calendarAllSourcesFailed': 'Kalenderdaten konnten nicht geladen werden.',
    'mobile.calendarSourceFailed': 'nicht geladen',
    'mobile.calendarLegend': 'Anzeige',
    'mobile.calendarCancellationTitle': 'Training fällt aus',
    'mobile.calendarCancellationHint': 'Blendet regelmäßige Trainingszeiten an den Tagen aus.',
    'mobile.calendarCancellationStart': 'Datum (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': 'Bis optional',
    'mobile.calendarCancellationReason': 'Grund',
    'mobile.calendarCancellationSave': 'Eintragen',
    'mobile.calendarCancellationInMonth': 'Ausfälle diesen Monat',
    'mobile.calendarGridTitle': 'Monat',
    'mobile.calendarAgendaTitle': 'Termine im Monat',
    'mobile.calendarAgendaEmpty': 'Keine Termine in diesem Monat.',
  },
  en: {
    'mobile.calendarSourceDiary': 'Diary',
    'mobile.calendarSourceTrainingTimes': 'Training times',
    'mobile.calendarSourceCancellations': 'Training cancellations',
    'mobile.calendarSourceTournaments': 'Tournaments',
    'mobile.calendarSourceMatches': 'League matches',
    'mobile.calendarSourceOfficial': 'Official participations',
    'mobile.calendarSourceHolidays': 'Holidays / school breaks',
    'mobile.calendarLegendTraining': 'Training',
    'mobile.calendarLegendTournament': 'Tournament',
    'mobile.calendarLegendOfficial': 'Participation',
    'mobile.calendarLegendMatch': 'League match',
    'mobile.calendarLegendHoliday': 'Public holiday',
    'mobile.calendarLegendSchool': 'School break',
    'mobile.calendarLegendCancellation': 'Cancellation',
    'mobile.calendarTitle': 'Calendar',
    'mobile.calendarSubtitle': 'Training, tournaments, matches and holidays for the month.',
    'mobile.calendarToday': 'Today',
    'mobile.calendarAllSourcesFailed': 'Calendar data could not be loaded.',
    'mobile.calendarSourceFailed': 'not loaded',
    'mobile.calendarLegend': 'Display',
    'mobile.calendarCancellationTitle': 'Training cancelled',
    'mobile.calendarCancellationHint': 'Hides recurring training times on those days.',
    'mobile.calendarCancellationStart': 'Date (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': 'Until (optional)',
    'mobile.calendarCancellationReason': 'Reason',
    'mobile.calendarCancellationSave': 'Save',
    'mobile.calendarCancellationInMonth': 'Cancellations this month',
    'mobile.calendarGridTitle': 'Month',
    'mobile.calendarAgendaTitle': 'Events this month',
    'mobile.calendarAgendaEmpty': 'No events in this month.',
  },
  es: {
    'mobile.calendarSourceDiary': 'Diario',
    'mobile.calendarSourceTrainingTimes': 'Horarios de entrenamiento',
    'mobile.calendarSourceCancellations': 'Cancelaciones',
    'mobile.calendarSourceTournaments': 'Torneos',
    'mobile.calendarSourceMatches': 'Partidos de liga',
    'mobile.calendarSourceOfficial': 'Participaciones oficiales',
    'mobile.calendarSourceHolidays': 'Vacaciones / festivos',
    'mobile.calendarLegendTraining': 'Entrenamiento',
    'mobile.calendarLegendTournament': 'Torneo',
    'mobile.calendarLegendOfficial': 'Participación',
    'mobile.calendarLegendMatch': 'Partido de liga',
    'mobile.calendarLegendHoliday': 'Festivo',
    'mobile.calendarLegendSchool': 'Vacaciones escolares',
    'mobile.calendarLegendCancellation': 'Cancelación',
    'mobile.calendarTitle': 'Calendario',
    'mobile.calendarSubtitle': 'Entrenamientos, torneos, partidos y festivos del mes.',
    'mobile.calendarToday': 'Hoy',
    'mobile.calendarAllSourcesFailed': 'No se pudieron cargar los datos del calendario.',
    'mobile.calendarSourceFailed': 'no cargado',
    'mobile.calendarLegend': 'Vista',
    'mobile.calendarCancellationTitle': 'Entrenamiento cancelado',
    'mobile.calendarCancellationHint': 'Oculta los horarios recurrentes en esos días.',
    'mobile.calendarCancellationStart': 'Fecha (AAAA-MM-DD)',
    'mobile.calendarCancellationEnd': 'Hasta (opcional)',
    'mobile.calendarCancellationReason': 'Motivo',
    'mobile.calendarCancellationSave': 'Guardar',
    'mobile.calendarCancellationInMonth': 'Cancelaciones este mes',
    'mobile.calendarGridTitle': 'Mes',
    'mobile.calendarAgendaTitle': 'Citas del mes',
    'mobile.calendarAgendaEmpty': 'No hay citas en este mes.',
  },
  fr: {
    'mobile.calendarSourceDiary': 'Journal',
    'mobile.calendarSourceTrainingTimes': 'Créneaux d’entraînement',
    'mobile.calendarSourceCancellations': 'Annulations',
    'mobile.calendarSourceTournaments': 'Tournois',
    'mobile.calendarSourceMatches': 'Matchs de championnat',
    'mobile.calendarSourceOfficial': 'Participations officielles',
    'mobile.calendarSourceHolidays': 'Vacances / jours fériés',
    'mobile.calendarLegendTraining': 'Entraînement',
    'mobile.calendarLegendTournament': 'Tournoi',
    'mobile.calendarLegendOfficial': 'Participation',
    'mobile.calendarLegendMatch': 'Match',
    'mobile.calendarLegendHoliday': 'Jour férié',
    'mobile.calendarLegendSchool': 'Vacances scolaires',
    'mobile.calendarLegendCancellation': 'Annulation',
    'mobile.calendarTitle': 'Calendrier',
    'mobile.calendarSubtitle': 'Entraînements, tournois, matchs et vacances du mois.',
    'mobile.calendarToday': 'Aujourd’hui',
    'mobile.calendarAllSourcesFailed': 'Impossible de charger le calendrier.',
    'mobile.calendarSourceFailed': 'non chargé',
    'mobile.calendarLegend': 'Affichage',
    'mobile.calendarCancellationTitle': 'Entraînement annulé',
    'mobile.calendarCancellationHint': 'Masque les créneaux récurrents ces jours-là.',
    'mobile.calendarCancellationStart': 'Date (AAAA-MM-JJ)',
    'mobile.calendarCancellationEnd': 'Jusqu’au (optionnel)',
    'mobile.calendarCancellationReason': 'Motif',
    'mobile.calendarCancellationSave': 'Enregistrer',
    'mobile.calendarCancellationInMonth': 'Annulations ce mois-ci',
    'mobile.calendarGridTitle': 'Mois',
    'mobile.calendarAgendaTitle': 'Rendez-vous du mois',
    'mobile.calendarAgendaEmpty': 'Aucun rendez-vous ce mois-ci.',
  },
  it: {
    'mobile.calendarSourceDiary': 'Diario',
    'mobile.calendarSourceTrainingTimes': 'Orari allenamento',
    'mobile.calendarSourceCancellations': 'Cancellazioni',
    'mobile.calendarSourceTournaments': 'Tornei',
    'mobile.calendarSourceMatches': 'Partite campionato',
    'mobile.calendarSourceOfficial': 'Partecipazioni ufficiali',
    'mobile.calendarSourceHolidays': 'Vacanze / festività',
    'mobile.calendarLegendTraining': 'Allenamento',
    'mobile.calendarLegendTournament': 'Torneo',
    'mobile.calendarLegendOfficial': 'Partecipazione',
    'mobile.calendarLegendMatch': 'Partita',
    'mobile.calendarLegendHoliday': 'Festività',
    'mobile.calendarLegendSchool': 'Vacanze scolastiche',
    'mobile.calendarLegendCancellation': 'Cancellazione',
    'mobile.calendarTitle': 'Calendario',
    'mobile.calendarSubtitle': 'Allenamenti, tornei, partite e festività del mese.',
    'mobile.calendarToday': 'Oggi',
    'mobile.calendarAllSourcesFailed': 'Impossibile caricare il calendario.',
    'mobile.calendarSourceFailed': 'non caricato',
    'mobile.calendarLegend': 'Vista',
    'mobile.calendarCancellationTitle': 'Allenamento annullato',
    'mobile.calendarCancellationHint': 'Nasconde gli orari ricorrenti in quei giorni.',
    'mobile.calendarCancellationStart': 'Data (AAAA-MM-GG)',
    'mobile.calendarCancellationEnd': 'Fino al (opzionale)',
    'mobile.calendarCancellationReason': 'Motivo',
    'mobile.calendarCancellationSave': 'Salva',
    'mobile.calendarCancellationInMonth': 'Cancellazioni questo mese',
    'mobile.calendarGridTitle': 'Mese',
    'mobile.calendarAgendaTitle': 'Appuntamenti del mese',
    'mobile.calendarAgendaEmpty': 'Nessun appuntamento in questo mese.',
  },
  pl: {
    'mobile.calendarSourceDiary': 'Dziennik',
    'mobile.calendarSourceTrainingTimes': 'Terminy treningów',
    'mobile.calendarSourceCancellations': 'Odwołania',
    'mobile.calendarSourceTournaments': 'Turnieje',
    'mobile.calendarSourceMatches': 'Mecze ligowe',
    'mobile.calendarSourceOfficial': 'Oficjalne starty',
    'mobile.calendarSourceHolidays': 'Święta / ferie',
    'mobile.calendarLegendTraining': 'Trening',
    'mobile.calendarLegendTournament': 'Turniej',
    'mobile.calendarLegendOfficial': 'Start',
    'mobile.calendarLegendMatch': 'Mecz',
    'mobile.calendarLegendHoliday': 'Święto',
    'mobile.calendarLegendSchool': 'Ferie',
    'mobile.calendarLegendCancellation': 'Odwołanie',
    'mobile.calendarTitle': 'Kalendarz',
    'mobile.calendarSubtitle': 'Treningi, turnieje, mecze i święta w miesiącu.',
    'mobile.calendarToday': 'Dziś',
    'mobile.calendarAllSourcesFailed': 'Nie udało się wczytać kalendarza.',
    'mobile.calendarSourceFailed': 'nie wczytano',
    'mobile.calendarLegend': 'Widok',
    'mobile.calendarCancellationTitle': 'Trening odwołany',
    'mobile.calendarCancellationHint': 'Ukrywa cykliczne terminy treningów w te dni.',
    'mobile.calendarCancellationStart': 'Data (RRRR-MM-DD)',
    'mobile.calendarCancellationEnd': 'Do (opcjonalnie)',
    'mobile.calendarCancellationReason': 'Powód',
    'mobile.calendarCancellationSave': 'Zapisz',
    'mobile.calendarCancellationInMonth': 'Odwołania w tym miesiącu',
    'mobile.calendarGridTitle': 'Miesiąc',
    'mobile.calendarAgendaTitle': 'Terminy w miesiącu',
    'mobile.calendarAgendaEmpty': 'Brak terminów w tym miesiącu.',
  },
  ja: {
    'mobile.calendarSourceDiary': '日記',
    'mobile.calendarSourceTrainingTimes': '練習時間',
    'mobile.calendarSourceCancellations': '練習中止',
    'mobile.calendarSourceTournaments': '大会',
    'mobile.calendarSourceMatches': 'リーグ戦',
    'mobile.calendarSourceOfficial': '公式参加',
    'mobile.calendarSourceHolidays': '休日・学校休暇',
    'mobile.calendarLegendTraining': '練習',
    'mobile.calendarLegendTournament': '大会',
    'mobile.calendarLegendOfficial': '参加',
    'mobile.calendarLegendMatch': 'リーグ戦',
    'mobile.calendarLegendHoliday': '祝日',
    'mobile.calendarLegendSchool': '学校の休み',
    'mobile.calendarLegendCancellation': '中止',
    'mobile.calendarTitle': 'カレンダー',
    'mobile.calendarSubtitle': '今月の練習・大会・試合・休日。',
    'mobile.calendarToday': '今日',
    'mobile.calendarAllSourcesFailed': 'カレンダーを読み込めませんでした。',
    'mobile.calendarSourceFailed': '未読込',
    'mobile.calendarLegend': '表示',
    'mobile.calendarCancellationTitle': '練習中止',
    'mobile.calendarCancellationHint': 'その日の定例練習時間を非表示にします。',
    'mobile.calendarCancellationStart': '日付 (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': '終了日（任意）',
    'mobile.calendarCancellationReason': '理由',
    'mobile.calendarCancellationSave': '保存',
    'mobile.calendarCancellationInMonth': '今月の中止',
    'mobile.calendarGridTitle': '月',
    'mobile.calendarAgendaTitle': '今月の予定',
    'mobile.calendarAgendaEmpty': '今月の予定はありません。',
  },
  zh: {
    'mobile.calendarSourceDiary': '日记',
    'mobile.calendarSourceTrainingTimes': '训练时间',
    'mobile.calendarSourceCancellations': '训练取消',
    'mobile.calendarSourceTournaments': '比赛',
    'mobile.calendarSourceMatches': '联赛',
    'mobile.calendarSourceOfficial': '官方参赛',
    'mobile.calendarSourceHolidays': '假期/节日',
    'mobile.calendarLegendTraining': '训练',
    'mobile.calendarLegendTournament': '锦标赛',
    'mobile.calendarLegendOfficial': '参赛',
    'mobile.calendarLegendMatch': '联赛',
    'mobile.calendarLegendHoliday': '节日',
    'mobile.calendarLegendSchool': '学校假期',
    'mobile.calendarLegendCancellation': '取消',
    'mobile.calendarTitle': '日历',
    'mobile.calendarSubtitle': '本月训练、比赛与假期一览。',
    'mobile.calendarToday': '今天',
    'mobile.calendarAllSourcesFailed': '无法加载日历数据。',
    'mobile.calendarSourceFailed': '未加载',
    'mobile.calendarLegend': '显示',
    'mobile.calendarCancellationTitle': '训练取消',
    'mobile.calendarCancellationHint': '在这些日期隐藏定期训练时间。',
    'mobile.calendarCancellationStart': '日期 (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': '结束（可选）',
    'mobile.calendarCancellationReason': '原因',
    'mobile.calendarCancellationSave': '保存',
    'mobile.calendarCancellationInMonth': '本月取消',
    'mobile.calendarGridTitle': '月份',
    'mobile.calendarAgendaTitle': '本月日程',
    'mobile.calendarAgendaEmpty': '本月没有日程。',
  },
  th: {
    'mobile.calendarSourceDiary': 'ไดอารี่',
    'mobile.calendarSourceTrainingTimes': 'เวลาฝึก',
    'mobile.calendarSourceCancellations': 'ยกเลิกการฝึก',
    'mobile.calendarSourceTournaments': 'การแข่งขัน',
    'mobile.calendarSourceMatches': 'แมตช์ลีก',
    'mobile.calendarSourceOfficial': 'การเข้าร่วมอย่างเป็นทางการ',
    'mobile.calendarSourceHolidays': 'วันหยุด/ปิดเทอม',
    'mobile.calendarLegendTraining': 'ฝึก',
    'mobile.calendarLegendTournament': 'ทัวร์นาเมนต์',
    'mobile.calendarLegendOfficial': 'เข้าร่วม',
    'mobile.calendarLegendMatch': 'แมตช์',
    'mobile.calendarLegendHoliday': 'วันหยุด',
    'mobile.calendarLegendSchool': 'ปิดเทอม',
    'mobile.calendarLegendCancellation': 'ยกเลิก',
    'mobile.calendarTitle': 'ปฏิทิน',
    'mobile.calendarSubtitle': 'การฝึก ทัวร์นาเมนต์ แมตช์ และวันหยุดในเดือนนี้',
    'mobile.calendarToday': 'วันนี้',
    'mobile.calendarAllSourcesFailed': 'โหลดข้อมูลปฏิทินไม่สำเร็จ',
    'mobile.calendarSourceFailed': 'ไม่ได้โหลด',
    'mobile.calendarLegend': 'แสดง',
    'mobile.calendarCancellationTitle': 'ยกเลิกการฝึก',
    'mobile.calendarCancellationHint': 'ซ่อนเวลาฝึกประจำในวันเหล่านั้น',
    'mobile.calendarCancellationStart': 'วันที่ (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': 'ถึง (ไม่บังคับ)',
    'mobile.calendarCancellationReason': 'เหตุผล',
    'mobile.calendarCancellationSave': 'บันทึก',
    'mobile.calendarCancellationInMonth': 'การยกเลิกในเดือนนี้',
    'mobile.calendarGridTitle': 'เดือน',
    'mobile.calendarAgendaTitle': 'นัดในเดือนนี้',
    'mobile.calendarAgendaEmpty': 'ไม่มีนัดในเดือนนี้',
  },
  tl: {
    'mobile.calendarSourceDiary': 'Diaryo',
    'mobile.calendarSourceTrainingTimes': 'Mga oras ng training',
    'mobile.calendarSourceCancellations': 'Mga pagkansela',
    'mobile.calendarSourceTournaments': 'Mga torneo',
    'mobile.calendarSourceMatches': 'Mga laban sa liga',
    'mobile.calendarSourceOfficial': 'Opisyal na pakikilahok',
    'mobile.calendarSourceHolidays': 'Holiday / bakasyon',
    'mobile.calendarLegendTraining': 'Training',
    'mobile.calendarLegendTournament': 'Torneo',
    'mobile.calendarLegendOfficial': 'Pakikilahok',
    'mobile.calendarLegendMatch': 'Laban',
    'mobile.calendarLegendHoliday': 'Holiday',
    'mobile.calendarLegendSchool': 'Bakasyon sa paaralan',
    'mobile.calendarLegendCancellation': 'Kansela',
    'mobile.calendarTitle': 'Kalendaryo',
    'mobile.calendarSubtitle': 'Training, torneo, liga at holiday sa buwan.',
    'mobile.calendarToday': 'Ngayon',
    'mobile.calendarAllSourcesFailed': 'Hindi ma-load ang kalendaryo.',
    'mobile.calendarSourceFailed': 'hindi na-load',
    'mobile.calendarLegend': 'Ipakita',
    'mobile.calendarCancellationTitle': 'Kanseladong training',
    'mobile.calendarCancellationHint': 'Itinatago ang paulit-ulit na oras ng training sa mga araw na iyon.',
    'mobile.calendarCancellationStart': 'Petsa (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': 'Hanggang (opsyonal)',
    'mobile.calendarCancellationReason': 'Dahilan',
    'mobile.calendarCancellationSave': 'I-save',
    'mobile.calendarCancellationInMonth': 'Mga kansela ngayong buwan',
    'mobile.calendarGridTitle': 'Buwan',
    'mobile.calendarAgendaTitle': 'Mga appointment sa buwan',
    'mobile.calendarAgendaEmpty': 'Walang appointment sa buwang ito.',
  },
  fil: {
    'mobile.calendarSourceDiary': 'Tala-arawan',
    'mobile.calendarSourceTrainingTimes': 'Mga oras ng pagsasanay',
    'mobile.calendarSourceCancellations': 'Mga pagkansela',
    'mobile.calendarSourceTournaments': 'Mga torneo',
    'mobile.calendarSourceMatches': 'Mga laban sa liga',
    'mobile.calendarSourceOfficial': 'Opisyal na pakikilahok',
    'mobile.calendarSourceHolidays': 'Holiday / bakasyon',
    'mobile.calendarLegendTraining': 'Pagsasanay',
    'mobile.calendarLegendTournament': 'Torneo',
    'mobile.calendarLegendOfficial': 'Pakikilahok',
    'mobile.calendarLegendMatch': 'Laban',
    'mobile.calendarLegendHoliday': 'Holiday',
    'mobile.calendarLegendSchool': 'Bakasyon sa paaralan',
    'mobile.calendarLegendCancellation': 'Kansela',
    'mobile.calendarTitle': 'Kalendaryo',
    'mobile.calendarSubtitle': 'Pagsasanay, torneo, liga at holiday sa buwan.',
    'mobile.calendarToday': 'Ngayon',
    'mobile.calendarAllSourcesFailed': 'Hindi ma-load ang kalendaryo.',
    'mobile.calendarSourceFailed': 'hindi na-load',
    'mobile.calendarLegend': 'Ipakita',
    'mobile.calendarCancellationTitle': 'Kinanselang pagsasanay',
    'mobile.calendarCancellationHint': 'Itinatago ang paulit-ulit na oras sa mga araw na iyon.',
    'mobile.calendarCancellationStart': 'Petsa (YYYY-MM-DD)',
    'mobile.calendarCancellationEnd': 'Hanggang (opsyonal)',
    'mobile.calendarCancellationReason': 'Dahilan',
    'mobile.calendarCancellationSave': 'I-save',
    'mobile.calendarCancellationInMonth': 'Mga kansela ngayong buwan',
    'mobile.calendarGridTitle': 'Buwan',
    'mobile.calendarAgendaTitle': 'Mga appointment sa buwan',
    'mobile.calendarAgendaEmpty': 'Walang appointment sa buwang ito.',
  },
};

function calendarStringsForLocale(code) {
  if (code === 'de' || code === 'de-CH' || code === 'de-extended') return MOBILE_CALENDAR_I18N.de;
  if (code.startsWith('en-')) return MOBILE_CALENDAR_I18N.en;
  if (code === 'es') return MOBILE_CALENDAR_I18N.es;
  if (code === 'fr') return MOBILE_CALENDAR_I18N.fr;
  if (code === 'it') return MOBILE_CALENDAR_I18N.it;
  if (code === 'pl') return MOBILE_CALENDAR_I18N.pl;
  if (code === 'ja') return MOBILE_CALENDAR_I18N.ja;
  if (code === 'zh') return MOBILE_CALENDAR_I18N.zh;
  if (code === 'th') return MOBILE_CALENDAR_I18N.th;
  if (code === 'tl' || code === 'fil') return MOBILE_CALENDAR_I18N[code === 'fil' ? 'fil' : 'tl'];
  return MOBILE_CALENDAR_I18N.en;
}

function flatten(obj, prefix = '', out = {}) {
  for (const [key, value] of Object.entries(obj || {})) {
    const nextKey = prefix ? `${prefix}.${key}` : key;
    if (value && typeof value === 'object' && !Array.isArray(value)) {
      flatten(value, nextKey, out);
    } else if (typeof value === 'string') {
      out[nextKey] = value;
    }
  }
  return out;
}

function escapeKotlinString(value) {
  return value
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
    .replace(/\r/g, '\\r')
    .replace(/\n/g, '\\n');
}

function kotlinIdentifier(code) {
  return code.replace(/[^A-Za-z0-9_]/g, '_');
}

function main() {
  const baseJson = JSON.parse(fs.readFileSync(path.join(SOURCE_DIR, 'de.json'), 'utf8'));
  const baseFlat = {
    ...flatten(baseJson),
    ...MOBILE_STRINGS.de,
  };
  const localeFiles = fs
    .readdirSync(SOURCE_DIR)
    .filter((file) => file.endsWith('.json') && !file.endsWith('.backup'))
    .sort((a, b) => a.localeCompare(b));

  const lines = [];
  lines.push('package de.tsschulz.tt_tagebuch.shared.i18n');
  lines.push('');
  lines.push('data class SupportedLanguage(val code: String, val label: String)');
  lines.push('');
  lines.push('object MobileStrings {');
  lines.push('    const val DEFAULT_LANGUAGE = "de"');
  lines.push('');
  lines.push('    val supportedLanguages: List<SupportedLanguage> = listOf(');
  for (const file of localeFiles) {
    const code = path.basename(file, '.json');
    lines.push(`        SupportedLanguage("${escapeKotlinString(code)}", "${escapeKotlinString(LOCALE_LABELS[code] || code)}"),`);
  }
  lines.push('    )');
  lines.push('');
  const baseEntries = Object.entries(baseFlat).sort(([a], [b]) => a.localeCompare(b));
  for (const file of localeFiles) {
    const code = path.basename(file, '.json');
    const localeJson = JSON.parse(fs.readFileSync(path.join(SOURCE_DIR, file), 'utf8'));
    const specificMobileStrings = MOBILE_STRINGS[code] || (code.startsWith('en-') ? MOBILE_STRINGS.en : {});
    const flat = {
      ...baseFlat,
      ...flatten(localeJson),
      ...specificMobileStrings,
      ...calendarStringsForLocale(code),
    };
    lines.push(`    private val ${kotlinIdentifier(code)}: Map<String, String> by lazy { mapOf(`);
    for (const [key, value] of Object.entries(flat).sort(([a], [b]) => a.localeCompare(b))) {
      lines.push(`        "${escapeKotlinString(key)}" to "${escapeKotlinString(value)}",`);
    }
    lines.push('    ) }');
    lines.push('');
  }
  lines.push(`    private val fallback: Map<String, String> get() = ${kotlinIdentifier('de')}`);
  lines.push('');
  lines.push('    fun get(languageCode: String, key: String, fallbackValue: String): String =');
  lines.push('        mapFor(languageCode)[key] ?: fallback[key] ?: fallbackValue');
  lines.push('');
  lines.push('    private fun mapFor(languageCode: String): Map<String, String> = when (languageCode) {');
  for (const file of localeFiles) {
    const code = path.basename(file, '.json');
    lines.push(`        "${escapeKotlinString(code)}" -> ${kotlinIdentifier(code)}`);
  }
  lines.push('        else -> fallback');
  lines.push('    }');
  lines.push('}');
  lines.push('');

  fs.mkdirSync(path.dirname(OUT), { recursive: true });
  fs.writeFileSync(OUT, lines.join('\n'), 'utf8');
  console.log(`Wrote ${OUT} (${localeFiles.length} locales, ${baseEntries.length} keys each)`);
}

main();
